veil-browser 0.2.0 → 0.2.1

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.
package/dist/browser.d.ts CHANGED
@@ -1,4 +1,10 @@
1
1
  import { Browser, BrowserContext, Page } from 'playwright';
2
+ export interface BrowserState {
3
+ platform: string;
4
+ pid: number;
5
+ wsEndpoint: string;
6
+ timestamp: number;
7
+ }
2
8
  export declare function ensureBrowser(opts?: {
3
9
  headed?: boolean;
4
10
  platform?: string;
@@ -8,5 +14,5 @@ export declare function ensureBrowser(opts?: {
8
14
  page: Page;
9
15
  }>;
10
16
  export declare function getPage(): Promise<Page | null>;
11
- export declare function closeBrowser(platform?: string): Promise<void>;
17
+ export declare function closeBrowser(_platform?: string): Promise<void>;
12
18
  export declare function humanDelay(min?: number, max?: number): Promise<void>;
package/dist/browser.js CHANGED
@@ -3,18 +3,20 @@ import { promises as fs } from 'fs';
3
3
  import { homedir } from 'os';
4
4
  import { join } from 'path';
5
5
  import { loadSession } from './session.js';
6
- const STATE_FILE = join(homedir(), '.veil', 'browser.json');
7
- // Singleton references (in-process)
6
+ const VEIL_DIR = join(homedir(), '.veil');
7
+ const STATE_FILE = join(VEIL_DIR, 'browser-state.json');
8
+ // In-process singletons
8
9
  let _browser = null;
9
10
  let _context = null;
10
11
  let _page = null;
11
- let _platform = 'default';
12
+ const STEALTH_UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36';
12
13
  export async function ensureBrowser(opts = {}) {
13
14
  const platform = opts.platform ?? 'default';
14
- if (_browser && _context && _page && !_page.isClosed()) {
15
+ // Return existing if healthy
16
+ if (_browser?.isConnected() && _page && !_page.isClosed()) {
15
17
  return { browser: _browser, context: _context, page: _page };
16
18
  }
17
- // Launch browser with stealth args
19
+ // Fresh browser launch
18
20
  const browser = await chromium.launch({
19
21
  headless: !opts.headed,
20
22
  args: [
@@ -25,51 +27,49 @@ export async function ensureBrowser(opts = {}) {
25
27
  '--disable-dev-shm-usage',
26
28
  '--disable-accelerated-2d-canvas',
27
29
  '--no-first-run',
28
- '--no-zygote',
29
- '--disable-gpu',
30
30
  '--window-size=1280,800',
31
- '--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
32
31
  ],
33
32
  });
34
- // Create context with realistic settings
35
33
  const context = await browser.newContext({
36
34
  viewport: { width: 1280, height: 800 },
37
- userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
35
+ userAgent: STEALTH_UA,
38
36
  locale: 'en-US',
39
37
  timezoneId: 'America/New_York',
40
38
  permissions: ['notifications'],
41
- extraHTTPHeaders: {
42
- 'Accept-Language': 'en-US,en;q=0.9',
43
- },
39
+ extraHTTPHeaders: { 'Accept-Language': 'en-US,en;q=0.9' },
44
40
  });
45
- // Inject stealth scripts
41
+ // Stealth: hide automation signals
46
42
  await context.addInitScript(() => {
47
43
  Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
48
44
  window.chrome = { runtime: {} };
49
- Object.defineProperty(navigator, 'plugins', {
50
- get: () => [1, 2, 3, 4, 5],
51
- });
52
- Object.defineProperty(navigator, 'languages', {
53
- get: () => ['en-US', 'en'],
54
- });
45
+ Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
46
+ Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
55
47
  });
56
- // Restore session cookies if available
57
- const session = await loadSession(platform);
58
- if (session?.cookies && session.cookies.length > 0) {
59
- await context.addCookies(session.cookies);
48
+ // Restore saved session cookies
49
+ const session = await loadSession(platform).catch(() => null);
50
+ if (session?.cookies?.length) {
51
+ await context.addCookies(session.cookies).catch(() => { });
60
52
  }
61
53
  const page = await context.newPage();
62
54
  _browser = browser;
63
55
  _context = context;
64
56
  _page = page;
65
- _platform = platform;
66
- // Save state for reference
67
- await fs.mkdir(join(homedir(), '.veil'), { recursive: true });
57
+ // Persist state for reconnection
58
+ await fs.mkdir(VEIL_DIR, { recursive: true });
68
59
  await fs.writeFile(STATE_FILE, JSON.stringify({
69
60
  platform,
70
61
  pid: process.pid,
62
+ wsEndpoint: '',
71
63
  timestamp: Date.now(),
72
64
  }), 'utf-8').catch(() => { });
65
+ // Cleanup state on exit
66
+ const cleanup = () => {
67
+ fs.rm(STATE_FILE).catch(() => { });
68
+ _browser?.close().catch(() => { });
69
+ };
70
+ process.once('exit', cleanup);
71
+ process.once('SIGINT', () => { cleanup(); process.exit(0); });
72
+ process.once('SIGTERM', () => { cleanup(); process.exit(0); });
73
73
  return { browser, context, page };
74
74
  }
75
75
  export async function getPage() {
@@ -77,16 +77,13 @@ export async function getPage() {
77
77
  return _page;
78
78
  return null;
79
79
  }
80
- export async function closeBrowser(platform) {
81
- if (_browser) {
82
- await _browser.close().catch(() => { });
83
- _browser = null;
84
- _context = null;
85
- _page = null;
86
- }
80
+ export async function closeBrowser(_platform) {
81
+ await _browser?.close().catch(() => { });
82
+ _browser = null;
83
+ _context = null;
84
+ _page = null;
87
85
  await fs.rm(STATE_FILE).catch(() => { });
88
86
  }
89
- export function humanDelay(min = 500, max = 1200) {
90
- const delay = Math.floor(Math.random() * (max - min) + min);
91
- return new Promise(r => setTimeout(r, delay));
87
+ export function humanDelay(min = 400, max = 900) {
88
+ return new Promise(r => setTimeout(r, Math.floor(Math.random() * (max - min) + min)));
92
89
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veil-browser",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Stealth browser CLI for AI agents — bypass bot detection, persist sessions, local CAPTCHA solving, MCP server",
5
5
  "keywords": [
6
6
  "browser",