@ulpi/browse 1.0.2 → 1.0.4

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/bin/browse ADDED
@@ -0,0 +1,8 @@
1
+ #!/bin/sh
2
+ SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
3
+ CLI="$SCRIPT_DIR/dist/browse.cjs"
4
+ if command -v bun >/dev/null 2>&1; then
5
+ exec bun "$CLI" "$@"
6
+ else
7
+ exec node "$CLI" "$@"
8
+ fi
package/bin/browse.ts ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env tsx
2
+ import { main } from '../src/cli';
3
+
4
+ if (process.env.__BROWSE_SERVER_MODE === '1') {
5
+ import('../src/server');
6
+ } else {
7
+ main().catch((err) => {
8
+ console.error(`[browse] ${err.message}`);
9
+ process.exit(1);
10
+ });
11
+ }
@@ -1,20 +1,16 @@
1
1
  #!/usr/bin/env node
2
+ const __import_meta_url = require("url").pathToFileURL(__filename).href;
3
+ "use strict";
2
4
  var __create = Object.create;
3
5
  var __defProp = Object.defineProperty;
4
6
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
8
  var __getProtoOf = Object.getPrototypeOf;
7
9
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
- }) : x)(function(x) {
11
- if (typeof require !== "undefined") return require.apply(this, arguments);
12
- throw Error('Dynamic require of "' + x + '" is not supported');
13
- });
14
10
  var __esm = (fn, res) => function __init() {
15
11
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
16
12
  };
17
- var __commonJS = (cb, mod) => function __require2() {
13
+ var __commonJS = (cb, mod) => function __require() {
18
14
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
19
15
  };
20
16
  var __export = (target, all) => {
@@ -38,6 +34,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
38
34
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
39
35
  mod
40
36
  ));
37
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
41
38
 
42
39
  // src/constants.ts
43
40
  var BROWSE_TIMEOUT, DEFAULTS;
@@ -68,9 +65,6 @@ var chrome_discover_exports = {};
68
65
  __export(chrome_discover_exports, {
69
66
  discoverChrome: () => discoverChrome
70
67
  });
71
- import * as os from "os";
72
- import * as fs2 from "fs";
73
- import * as path2 from "path";
74
68
  async function fetchWsUrl(port) {
75
69
  try {
76
70
  const res = await fetch(`http://127.0.0.1:${port}/json/version`, {
@@ -108,10 +102,13 @@ async function discoverChrome() {
108
102
  }
109
103
  return null;
110
104
  }
111
- var PROFILE_PATHS, PROBE_PORTS;
105
+ var os, fs2, path2, PROFILE_PATHS, PROBE_PORTS;
112
106
  var init_chrome_discover = __esm({
113
107
  "src/chrome-discover.ts"() {
114
108
  "use strict";
109
+ os = __toESM(require("os"), 1);
110
+ fs2 = __toESM(require("fs"), 1);
111
+ path2 = __toESM(require("path"), 1);
115
112
  PROFILE_PATHS = [
116
113
  "Google/Chrome",
117
114
  "Arc/User Data",
@@ -124,10 +121,10 @@ var init_chrome_discover = __esm({
124
121
 
125
122
  // package.json
126
123
  var require_package = __commonJS({
127
- "package.json"(exports, module) {
128
- module.exports = {
124
+ "package.json"(exports2, module2) {
125
+ module2.exports = {
129
126
  name: "@ulpi/browse",
130
- version: "1.0.2",
127
+ version: "1.0.4",
131
128
  repository: {
132
129
  type: "git",
133
130
  url: "https://github.com/ulpi-io/browse"
@@ -141,13 +138,14 @@ var require_package = __commonJS({
141
138
  "playwright-core": "^1.58.2"
142
139
  },
143
140
  bin: {
144
- browse: "dist/browse.mjs"
141
+ browse: "bin/browse"
145
142
  },
146
143
  description: "Fast headless browser CLI \u2014 persistent Chromium daemon via Playwright.",
147
144
  engines: {
148
145
  node: ">=18.0.0"
149
146
  },
150
147
  files: [
148
+ "bin/",
151
149
  "dist/",
152
150
  "skill/",
153
151
  "LICENSE",
@@ -168,7 +166,8 @@ var require_package = __commonJS({
168
166
  access: "public"
169
167
  },
170
168
  scripts: {
171
- build: "esbuild src/cli.ts --bundle --format=esm --platform=node --target=node18 --outfile=dist/browse.mjs --external:playwright --external:playwright-core --external:better-sqlite3 --external:electron --external:chromium-bidi --banner:js='#!/usr/bin/env node'",
169
+ build: `esbuild src/cli.ts --bundle --format=cjs --platform=node --target=node18 --outfile=dist/browse.cjs --external:playwright --external:playwright-core --external:better-sqlite3 --external:electron --external:chromium-bidi --banner:js='#!/usr/bin/env node
170
+ const __import_meta_url = require("url").pathToFileURL(__filename).href;' --define:import.meta.url=__import_meta_url`,
172
171
  "build:all": "bash scripts/build-all.sh",
173
172
  dev: "tsx src/cli.ts",
174
173
  server: "tsx src/server.ts",
@@ -199,9 +198,6 @@ var install_skill_exports = {};
199
198
  __export(install_skill_exports, {
200
199
  installSkill: () => installSkill
201
200
  });
202
- import * as fs3 from "fs";
203
- import * as path3 from "path";
204
- import { fileURLToPath } from "url";
205
201
  function installSkill(targetDir) {
206
202
  const dir = targetDir || process.cwd();
207
203
  const hasGit = fs3.existsSync(path3.join(dir, ".git"));
@@ -213,7 +209,7 @@ function installSkill(targetDir) {
213
209
  }
214
210
  const skillDir = path3.join(dir, ".claude", "skills", "browse");
215
211
  fs3.mkdirSync(skillDir, { recursive: true });
216
- const skillSource = path3.resolve(path3.dirname(fileURLToPath(import.meta.url)), "..", "skill", "SKILL.md");
212
+ const skillSource = path3.resolve(path3.dirname((0, import_url.fileURLToPath)(__import_meta_url)), "..", "skill", "SKILL.md");
217
213
  const skillDest = path3.join(skillDir, "SKILL.md");
218
214
  if (!fs3.existsSync(skillSource)) {
219
215
  console.error(`SKILL.md not found at ${skillSource}`);
@@ -250,10 +246,13 @@ function installSkill(targetDir) {
250
246
  }
251
247
  console.log("\nDone. Claude Code will now use browse for web tasks automatically.");
252
248
  }
253
- var PERMISSIONS;
249
+ var fs3, path3, import_url, PERMISSIONS;
254
250
  var init_install_skill = __esm({
255
251
  "src/install-skill.ts"() {
256
252
  "use strict";
253
+ fs3 = __toESM(require("fs"), 1);
254
+ path3 = __toESM(require("path"), 1);
255
+ import_url = require("url");
257
256
  PERMISSIONS = [
258
257
  "Bash(browse:*)",
259
258
  "Bash(browse goto:*)",
@@ -319,35 +318,29 @@ var rebrowser_playwright_exports = {};
319
318
  __export(rebrowser_playwright_exports, {
320
319
  default: () => rebrowser_playwright_default
321
320
  });
322
- import * as playwright_core_star from "playwright-core";
323
- import playwright from "playwright-core";
324
- var rebrowser_playwright_default;
321
+ var import_playwright_core, rebrowser_playwright_default;
325
322
  var init_rebrowser_playwright = __esm({
326
323
  "node_modules/rebrowser-playwright/index.mjs"() {
327
- __reExport(rebrowser_playwright_exports, playwright_core_star);
328
- rebrowser_playwright_default = playwright;
324
+ __reExport(rebrowser_playwright_exports, require("playwright-core"));
325
+ import_playwright_core = __toESM(require("playwright-core"), 1);
326
+ rebrowser_playwright_default = import_playwright_core.default;
329
327
  }
330
328
  });
331
329
 
332
330
  // src/runtime.ts
333
- import { homedir as homedir2 } from "os";
334
- import { existsSync as existsSync3 } from "fs";
335
- import { execSync, spawn } from "child_process";
336
- import { join as join4 } from "path";
337
- import * as net from "net";
338
331
  function findLightpanda() {
339
332
  try {
340
- const result = execSync("which lightpanda", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
333
+ const result = (0, import_child_process.execSync)("which lightpanda", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
341
334
  if (result) return result;
342
335
  } catch {
343
336
  }
344
- const home = homedir2();
337
+ const home = (0, import_os.homedir)();
345
338
  const candidates = [
346
- join4(home, ".lightpanda", "lightpanda"),
347
- join4(home, ".local", "bin", "lightpanda")
339
+ (0, import_path.join)(home, ".lightpanda", "lightpanda"),
340
+ (0, import_path.join)(home, ".local", "bin", "lightpanda")
348
341
  ];
349
342
  for (const candidate of candidates) {
350
- if (existsSync3(candidate)) return candidate;
343
+ if ((0, import_fs.existsSync)(candidate)) return candidate;
351
344
  }
352
345
  return null;
353
346
  }
@@ -361,10 +354,15 @@ async function getRuntime(name) {
361
354
  }
362
355
  return loader();
363
356
  }
364
- var registry, AVAILABLE_RUNTIMES;
357
+ var import_os, import_fs, import_child_process, import_path, net, registry, AVAILABLE_RUNTIMES;
365
358
  var init_runtime = __esm({
366
359
  "src/runtime.ts"() {
367
360
  "use strict";
361
+ import_os = require("os");
362
+ import_fs = require("fs");
363
+ import_child_process = require("child_process");
364
+ import_path = require("path");
365
+ net = __toESM(require("net"), 1);
368
366
  registry = {
369
367
  playwright: async () => {
370
368
  const pw = await import("playwright");
@@ -396,7 +394,7 @@ var init_runtime = __esm({
396
394
  });
397
395
  srv.on("error", reject);
398
396
  });
399
- const child = spawn(
397
+ const child = (0, import_child_process.spawn)(
400
398
  binaryPath,
401
399
  ["serve", "--host", "127.0.0.1", "--port", String(port), "--timeout", "604800"],
402
400
  { stdio: ["ignore", "pipe", "pipe"] }
@@ -536,23 +534,20 @@ __export(browser_manager_exports, {
536
534
  listProfiles: () => listProfiles,
537
535
  resolveDevice: () => resolveDevice
538
536
  });
539
- import * as path4 from "path";
540
- import * as fs4 from "fs";
541
- import { chromium, devices as playwrightDevices } from "playwright";
542
537
  function resolveDevice(name) {
543
538
  const alias = DEVICE_ALIASES[name.toLowerCase()];
544
539
  const aliasTarget = alias || name;
545
540
  if (CUSTOM_DEVICES[aliasTarget]) {
546
541
  return CUSTOM_DEVICES[aliasTarget];
547
542
  }
548
- if (playwrightDevices[aliasTarget]) {
549
- return playwrightDevices[aliasTarget];
543
+ if (import_playwright.devices[aliasTarget]) {
544
+ return import_playwright.devices[aliasTarget];
550
545
  }
551
546
  const lower = name.toLowerCase();
552
547
  for (const [key, desc] of Object.entries(CUSTOM_DEVICES)) {
553
548
  if (key.toLowerCase() === lower) return desc;
554
549
  }
555
- for (const [key, desc] of Object.entries(playwrightDevices)) {
550
+ for (const [key, desc] of Object.entries(import_playwright.devices)) {
556
551
  if (key.toLowerCase() === lower) {
557
552
  return desc;
558
553
  }
@@ -562,7 +557,7 @@ function resolveDevice(name) {
562
557
  function listDevices() {
563
558
  const all = /* @__PURE__ */ new Set([
564
559
  ...Object.keys(CUSTOM_DEVICES),
565
- ...Object.keys(playwrightDevices)
560
+ ...Object.keys(import_playwright.devices)
566
561
  ]);
567
562
  return [...all].sort();
568
563
  }
@@ -603,10 +598,13 @@ function deleteProfile(localDir, name) {
603
598
  if (!fs4.existsSync(dir)) throw new Error(`Profile "${name}" not found`);
604
599
  fs4.rmSync(dir, { recursive: true, force: true });
605
600
  }
606
- var DEVICE_ALIASES, CUSTOM_DEVICES, BrowserManager;
601
+ var path4, fs4, import_playwright, DEVICE_ALIASES, CUSTOM_DEVICES, BrowserManager;
607
602
  var init_browser_manager = __esm({
608
603
  "src/browser-manager.ts"() {
609
604
  "use strict";
605
+ path4 = __toESM(require("path"), 1);
606
+ fs4 = __toESM(require("fs"), 1);
607
+ import_playwright = require("playwright");
610
608
  init_buffers();
611
609
  init_sanitize();
612
610
  DEVICE_ALIASES = {
@@ -737,7 +735,7 @@ var init_browser_manager = __esm({
737
735
  * This instance owns the browser and will close it on close().
738
736
  */
739
737
  async launch(onCrash) {
740
- this.browser = await chromium.launch({ headless: true });
738
+ this.browser = await import_playwright.chromium.launch({ headless: true });
741
739
  this.ownsBrowser = true;
742
740
  this.browser.on("disconnected", () => {
743
741
  if (onCrash) onCrash();
@@ -770,7 +768,7 @@ var init_browser_manager = __esm({
770
768
  async launchPersistent(profileDir, onCrash) {
771
769
  let context;
772
770
  try {
773
- context = await chromium.launchPersistentContext(profileDir, {
771
+ context = await import_playwright.chromium.launchPersistentContext(profileDir, {
774
772
  headless: process.env.BROWSE_HEADED !== "1",
775
773
  viewport: { width: 1920, height: 1080 },
776
774
  ...this.customUserAgent ? { userAgent: this.customUserAgent } : {}
@@ -780,7 +778,7 @@ var init_browser_manager = __esm({
780
778
  const fs16 = await import("fs");
781
779
  console.error(`[browse] Profile directory corrupted, recreating: ${profileDir}`);
782
780
  fs16.rmSync(profileDir, { recursive: true, force: true });
783
- context = await chromium.launchPersistentContext(profileDir, {
781
+ context = await import_playwright.chromium.launchPersistentContext(profileDir, {
784
782
  headless: process.env.BROWSE_HEADED !== "1",
785
783
  viewport: { width: 1920, height: 1080 }
786
784
  });
@@ -1587,9 +1585,6 @@ var init_domain_filter = __esm({
1587
1585
  });
1588
1586
 
1589
1587
  // src/encryption.ts
1590
- import * as crypto from "crypto";
1591
- import * as fs5 from "fs";
1592
- import * as path5 from "path";
1593
1588
  function resolveEncryptionKey(localDir) {
1594
1589
  const envKey = process.env.BROWSE_ENCRYPTION_KEY;
1595
1590
  if (envKey) {
@@ -1630,9 +1625,13 @@ function decrypt(ciphertext, iv, authTag, key) {
1630
1625
  ]);
1631
1626
  return decrypted.toString("utf-8");
1632
1627
  }
1628
+ var crypto, fs5, path5;
1633
1629
  var init_encryption = __esm({
1634
1630
  "src/encryption.ts"() {
1635
1631
  "use strict";
1632
+ crypto = __toESM(require("crypto"), 1);
1633
+ fs5 = __toESM(require("fs"), 1);
1634
+ path5 = __toESM(require("path"), 1);
1636
1635
  }
1637
1636
  });
1638
1637
 
@@ -1644,8 +1643,6 @@ __export(session_persist_exports, {
1644
1643
  loadSessionState: () => loadSessionState,
1645
1644
  saveSessionState: () => saveSessionState
1646
1645
  });
1647
- import * as fs6 from "fs";
1648
- import * as path6 from "path";
1649
1646
  async function saveSessionState(sessionDir, context, encryptionKey) {
1650
1647
  try {
1651
1648
  const state = await context.storageState();
@@ -1779,19 +1776,19 @@ function cleanOldStates(localDir, maxAgeDays) {
1779
1776
  }
1780
1777
  return { deleted };
1781
1778
  }
1782
- var STATE_FILENAME;
1779
+ var fs6, path6, STATE_FILENAME;
1783
1780
  var init_session_persist = __esm({
1784
1781
  "src/session-persist.ts"() {
1785
1782
  "use strict";
1783
+ fs6 = __toESM(require("fs"), 1);
1784
+ path6 = __toESM(require("path"), 1);
1786
1785
  init_encryption();
1787
1786
  STATE_FILENAME = "state.json";
1788
1787
  }
1789
1788
  });
1790
1789
 
1791
1790
  // src/session-manager.ts
1792
- import * as fs7 from "fs";
1793
- import * as path7 from "path";
1794
- var SessionManager;
1791
+ var fs7, path7, SessionManager;
1795
1792
  var init_session_manager = __esm({
1796
1793
  "src/session-manager.ts"() {
1797
1794
  "use strict";
@@ -1801,6 +1798,8 @@ var init_session_manager = __esm({
1801
1798
  init_sanitize();
1802
1799
  init_session_persist();
1803
1800
  init_encryption();
1801
+ fs7 = __toESM(require("fs"), 1);
1802
+ path7 = __toESM(require("path"), 1);
1804
1803
  SessionManager = class {
1805
1804
  sessions = /* @__PURE__ */ new Map();
1806
1805
  browser;
@@ -1990,7 +1989,6 @@ var read_exports = {};
1990
1989
  __export(read_exports, {
1991
1990
  handleReadCommand: () => handleReadCommand
1992
1991
  });
1993
- import * as fs8 from "fs";
1994
1992
  async function handleReadCommand(command, args, bm, buffers) {
1995
1993
  const page = bm.getPage();
1996
1994
  const evalCtx = await bm.getFrameContext() || page;
@@ -2324,11 +2322,13 @@ async function handleReadCommand(command, args, bm, buffers) {
2324
2322
  throw new Error(`Unknown read command: ${command}`);
2325
2323
  }
2326
2324
  }
2325
+ var fs8;
2327
2326
  var init_read = __esm({
2328
2327
  "src/commands/read.ts"() {
2329
2328
  "use strict";
2330
2329
  init_browser_manager();
2331
2330
  init_constants();
2331
+ fs8 = __toESM(require("fs"), 1);
2332
2332
  }
2333
2333
  });
2334
2334
 
@@ -2337,7 +2337,6 @@ var write_exports = {};
2337
2337
  __export(write_exports, {
2338
2338
  handleWriteCommand: () => handleWriteCommand
2339
2339
  });
2340
- import * as fs9 from "fs";
2341
2340
  async function rebuildRoutes(context, bm, domainFilter) {
2342
2341
  await context.unrouteAll();
2343
2342
  for (const r of bm.getUserRoutes()) {
@@ -2951,11 +2950,13 @@ Note: Cookies and tab URLs preserved. localStorage/sessionStorage were reset (Pl
2951
2950
  throw new Error(`Unknown write command: ${command}`);
2952
2951
  }
2953
2952
  }
2953
+ var fs9;
2954
2954
  var init_write = __esm({
2955
2955
  "src/commands/write.ts"() {
2956
2956
  "use strict";
2957
2957
  init_browser_manager();
2958
2958
  init_constants();
2959
+ fs9 = __toESM(require("fs"), 1);
2959
2960
  }
2960
2961
  });
2961
2962
 
@@ -3919,8 +3920,6 @@ var policy_exports = {};
3919
3920
  __export(policy_exports, {
3920
3921
  PolicyChecker: () => PolicyChecker
3921
3922
  });
3922
- import * as fs10 from "fs";
3923
- import * as path8 from "path";
3924
3923
  function findFileUpward(filename) {
3925
3924
  let dir = process.cwd();
3926
3925
  for (let i = 0; i < 20; i++) {
@@ -3932,10 +3931,12 @@ function findFileUpward(filename) {
3932
3931
  }
3933
3932
  return null;
3934
3933
  }
3935
- var PolicyChecker;
3934
+ var fs10, path8, PolicyChecker;
3936
3935
  var init_policy = __esm({
3937
3936
  "src/policy.ts"() {
3938
3937
  "use strict";
3938
+ fs10 = __toESM(require("fs"), 1);
3939
+ path8 = __toESM(require("path"), 1);
3939
3940
  PolicyChecker = class {
3940
3941
  filePath = null;
3941
3942
  lastMtime = 0;
@@ -3988,7 +3989,6 @@ __export(png_compare_exports, {
3988
3989
  encodePNG: () => encodePNG,
3989
3990
  generateDiffImage: () => generateDiffImage
3990
3991
  });
3991
- import * as zlib from "zlib";
3992
3992
  function decodePNG(buf) {
3993
3993
  for (let i = 0; i < 8; i++) {
3994
3994
  if (buf[i] !== PNG_MAGIC[i]) throw new Error("Not a valid PNG file");
@@ -4163,10 +4163,11 @@ function compareScreenshots(baselineBuf, currentBuf, thresholdPct = 0.1, colorTh
4163
4163
  }
4164
4164
  return result;
4165
4165
  }
4166
- var PNG_MAGIC;
4166
+ var zlib, PNG_MAGIC;
4167
4167
  var init_png_compare = __esm({
4168
4168
  "src/png-compare.ts"() {
4169
4169
  "use strict";
4170
+ zlib = __toESM(require("zlib"), 1);
4170
4171
  PNG_MAGIC = [137, 80, 78, 71, 13, 10, 26, 10];
4171
4172
  }
4172
4173
  });
@@ -4176,8 +4177,6 @@ var auth_vault_exports = {};
4176
4177
  __export(auth_vault_exports, {
4177
4178
  AuthVault: () => AuthVault
4178
4179
  });
4179
- import * as fs11 from "fs";
4180
- import * as path9 from "path";
4181
4180
  async function autoDetectSelector(page, field) {
4182
4181
  if (field === "username") {
4183
4182
  const candidates2 = [
@@ -4224,10 +4223,12 @@ async function autoDetectSelector(page, field) {
4224
4223
  }
4225
4224
  throw new Error("Could not auto-detect submit button.");
4226
4225
  }
4227
- var AuthVault;
4226
+ var fs11, path9, AuthVault;
4228
4227
  var init_auth_vault = __esm({
4229
4228
  "src/auth-vault.ts"() {
4230
4229
  "use strict";
4230
+ fs11 = __toESM(require("fs"), 1);
4231
+ path9 = __toESM(require("path"), 1);
4231
4232
  init_constants();
4232
4233
  init_encryption();
4233
4234
  init_sanitize();
@@ -4321,12 +4322,6 @@ __export(cookie_import_exports, {
4321
4322
  importCookies: () => importCookies,
4322
4323
  listDomains: () => listDomains
4323
4324
  });
4324
- import Database from "better-sqlite3";
4325
- import { spawn as spawn2 } from "child_process";
4326
- import * as crypto2 from "crypto";
4327
- import * as fs12 from "fs";
4328
- import * as path10 from "path";
4329
- import * as os2 from "os";
4330
4325
  function findInstalledBrowsers() {
4331
4326
  const appSupport = path10.join(os2.homedir(), "Library", "Application Support");
4332
4327
  return BROWSER_REGISTRY.filter((b) => {
@@ -4427,7 +4422,7 @@ function getCookieDbPath(browser2, profile) {
4427
4422
  }
4428
4423
  function openDb(dbPath, browserName) {
4429
4424
  try {
4430
- return new Database(dbPath, { readonly: true });
4425
+ return new import_better_sqlite3.default(dbPath, { readonly: true });
4431
4426
  } catch (err) {
4432
4427
  if (err.message?.includes("SQLITE_BUSY") || err.message?.includes("database is locked")) {
4433
4428
  return openDbFromCopy(dbPath, browserName);
@@ -4449,7 +4444,7 @@ function openDbFromCopy(dbPath, browserName) {
4449
4444
  const shmPath = dbPath + "-shm";
4450
4445
  if (fs12.existsSync(walPath)) fs12.copyFileSync(walPath, tmpPath + "-wal");
4451
4446
  if (fs12.existsSync(shmPath)) fs12.copyFileSync(shmPath, tmpPath + "-shm");
4452
- const db = new Database(tmpPath, { readonly: true });
4447
+ const db = new import_better_sqlite3.default(tmpPath, { readonly: true });
4453
4448
  const origClose = db.close.bind(db);
4454
4449
  db.close = (() => {
4455
4450
  origClose();
@@ -4488,7 +4483,7 @@ async function getDerivedKey(browser2) {
4488
4483
  return derived;
4489
4484
  }
4490
4485
  async function getKeychainPassword(service) {
4491
- const proc = spawn2("security", ["find-generic-password", "-s", service, "-w"], {
4486
+ const proc = (0, import_child_process2.spawn)("security", ["find-generic-password", "-s", service, "-w"], {
4492
4487
  stdio: ["ignore", "pipe", "pipe"]
4493
4488
  });
4494
4489
  let stdout = "";
@@ -4595,10 +4590,16 @@ function mapSameSite(value) {
4595
4590
  return "Lax";
4596
4591
  }
4597
4592
  }
4598
- var CookieImportError, BROWSER_REGISTRY, keyCache, CHROMIUM_EPOCH_OFFSET;
4593
+ var import_better_sqlite3, import_child_process2, crypto2, fs12, path10, os2, CookieImportError, BROWSER_REGISTRY, keyCache, CHROMIUM_EPOCH_OFFSET;
4599
4594
  var init_cookie_import = __esm({
4600
4595
  "src/cookie-import.ts"() {
4601
4596
  "use strict";
4597
+ import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
4598
+ import_child_process2 = require("child_process");
4599
+ crypto2 = __toESM(require("crypto"), 1);
4600
+ fs12 = __toESM(require("fs"), 1);
4601
+ path10 = __toESM(require("path"), 1);
4602
+ os2 = __toESM(require("os"), 1);
4602
4603
  CookieImportError = class extends Error {
4603
4604
  constructor(message, code, action) {
4604
4605
  super(message);
@@ -4767,7 +4768,6 @@ var init_record_export = __esm({
4767
4768
  });
4768
4769
 
4769
4770
  // src/commands/meta.ts
4770
- import * as fs13 from "fs";
4771
4771
  async function handleMetaCommand(command, args, bm, shutdown2, sessionManager2, currentSession) {
4772
4772
  switch (command) {
4773
4773
  // ─── Tabs ──────────────────────────────────────────
@@ -5666,7 +5666,7 @@ Manual: npm install -g @ulpi/browse`;
5666
5666
  throw new Error(`Unknown meta command: ${command}`);
5667
5667
  }
5668
5668
  }
5669
- var LOCAL_DIR;
5669
+ var fs13, LOCAL_DIR;
5670
5670
  var init_meta = __esm({
5671
5671
  "src/commands/meta.ts"() {
5672
5672
  "use strict";
@@ -5674,18 +5674,13 @@ var init_meta = __esm({
5674
5674
  init_constants();
5675
5675
  init_sanitize();
5676
5676
  init_lib();
5677
+ fs13 = __toESM(require("fs"), 1);
5677
5678
  LOCAL_DIR = process.env.BROWSE_LOCAL_DIR || "/tmp";
5678
5679
  }
5679
5680
  });
5680
5681
 
5681
5682
  // src/server.ts
5682
5683
  var server_exports = {};
5683
- import * as fs14 from "fs";
5684
- import * as path11 from "path";
5685
- import * as crypto3 from "crypto";
5686
- import * as http from "http";
5687
- import { fileURLToPath as fileURLToPath2 } from "url";
5688
- import * as net2 from "net";
5689
5684
  function nodeServe(opts) {
5690
5685
  const server = http.createServer(async (nodeReq, nodeRes) => {
5691
5686
  try {
@@ -6097,7 +6092,7 @@ async function start() {
6097
6092
  port,
6098
6093
  token: AUTH_TOKEN,
6099
6094
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
6100
- serverPath: path11.resolve(path11.dirname(fileURLToPath2(import.meta.url)), "server.ts")
6095
+ serverPath: path11.resolve(path11.dirname((0, import_url2.fileURLToPath)(__import_meta_url)), "server.ts")
6101
6096
  };
6102
6097
  if (profileName) {
6103
6098
  state.profile = profileName;
@@ -6110,7 +6105,7 @@ async function start() {
6110
6105
  console.log(`[browse] State file: ${STATE_FILE}`);
6111
6106
  console.log(`[browse] Idle timeout: ${IDLE_TIMEOUT_MS / 1e3}s`);
6112
6107
  }
6113
- var AUTH_TOKEN, DEBUG_PORT, BROWSE_PORT, BROWSE_INSTANCE, INSTANCE_SUFFIX, LOCAL_DIR2, STATE_FILE, IDLE_TIMEOUT_MS, sessionManager, browser, profileSession, activeRuntime, isShuttingDown, isRemoteBrowser, policyChecker, READ_COMMANDS, WRITE_COMMANDS, META_COMMANDS, RECORDING_SKIP, PAGE_CONTENT_COMMANDS, BOUNDARY_NONCE, flushInterval, sessionCleanupInterval;
6108
+ var fs14, path11, crypto3, http, import_url2, net2, AUTH_TOKEN, DEBUG_PORT, BROWSE_PORT, BROWSE_INSTANCE, INSTANCE_SUFFIX, LOCAL_DIR2, STATE_FILE, IDLE_TIMEOUT_MS, sessionManager, browser, profileSession, activeRuntime, isShuttingDown, isRemoteBrowser, policyChecker, READ_COMMANDS, WRITE_COMMANDS, META_COMMANDS, RECORDING_SKIP, PAGE_CONTENT_COMMANDS, BOUNDARY_NONCE, flushInterval, sessionCleanupInterval;
6114
6109
  var init_server = __esm({
6115
6110
  "src/server.ts"() {
6116
6111
  "use strict";
@@ -6121,6 +6116,12 @@ var init_server = __esm({
6121
6116
  init_meta();
6122
6117
  init_policy();
6123
6118
  init_constants();
6119
+ fs14 = __toESM(require("fs"), 1);
6120
+ path11 = __toESM(require("path"), 1);
6121
+ crypto3 = __toESM(require("crypto"), 1);
6122
+ http = __toESM(require("http"), 1);
6123
+ import_url2 = require("url");
6124
+ net2 = __toESM(require("net"), 1);
6124
6125
  AUTH_TOKEN = crypto3.randomUUID();
6125
6126
  DEBUG_PORT = parseInt(process.env.BROWSE_DEBUG_PORT || "0", 10);
6126
6127
  BROWSE_PORT = parseInt(process.env.BROWSE_PORT || "0", 10);
@@ -6291,15 +6292,22 @@ var init_server = __esm({
6291
6292
  });
6292
6293
 
6293
6294
  // src/cli.ts
6295
+ var cli_exports = {};
6296
+ __export(cli_exports, {
6297
+ SAFE_TO_RETRY: () => SAFE_TO_RETRY,
6298
+ main: () => main,
6299
+ resolveServerScript: () => resolveServerScript
6300
+ });
6301
+ module.exports = __toCommonJS(cli_exports);
6302
+ var fs15 = __toESM(require("fs"), 1);
6303
+ var path12 = __toESM(require("path"), 1);
6304
+ var import_child_process3 = require("child_process");
6305
+ var import_url3 = require("url");
6294
6306
  init_constants();
6295
- import * as fs15 from "fs";
6296
- import * as path12 from "path";
6297
- import { spawn as spawn3 } from "child_process";
6298
- import { fileURLToPath as fileURLToPath3 } from "url";
6299
6307
 
6300
6308
  // src/config.ts
6301
- import * as fs from "fs";
6302
- import * as path from "path";
6309
+ var fs = __toESM(require("fs"), 1);
6310
+ var path = __toESM(require("path"), 1);
6303
6311
  function loadConfig() {
6304
6312
  let dir = process.cwd();
6305
6313
  for (let i = 0; i < 20; i++) {
@@ -6376,7 +6384,7 @@ var STATE_FILE2 = process.env.BROWSE_STATE_FILE || path12.join(LOCAL_DIR3, `brow
6376
6384
  var MAX_START_WAIT = 8e3;
6377
6385
  var LOCK_FILE = STATE_FILE2 + ".lock";
6378
6386
  var LOCK_STALE_MS = DEFAULTS.LOCK_STALE_THRESHOLD_MS;
6379
- var __filename_cli = fileURLToPath3(import.meta.url);
6387
+ var __filename_cli = (0, import_url3.fileURLToPath)(__import_meta_url);
6380
6388
  var __dirname_cli = path12.dirname(__filename_cli);
6381
6389
  function resolveServerScript(env = process.env, metaDir = __dirname_cli) {
6382
6390
  if (env.BROWSE_SERVER_SCRIPT) {
@@ -6388,7 +6396,7 @@ function resolveServerScript(env = process.env, metaDir = __dirname_cli) {
6388
6396
  return direct;
6389
6397
  }
6390
6398
  }
6391
- const selfPath = fileURLToPath3(import.meta.url);
6399
+ const selfPath = (0, import_url3.fileURLToPath)(__import_meta_url);
6392
6400
  if (fs15.existsSync(selfPath)) {
6393
6401
  return "__self__";
6394
6402
  }
@@ -6462,7 +6470,7 @@ async function listInstances() {
6462
6470
  }
6463
6471
  function isBrowseProcess(pid) {
6464
6472
  try {
6465
- const { execSync: execSync2 } = __require("child_process");
6473
+ const { execSync: execSync2 } = require("child_process");
6466
6474
  const cmd = execSync2(`ps -p ${pid} -o command=`, { encoding: "utf-8" }).trim();
6467
6475
  return cmd.includes("browse") || cmd.includes("__BROWSE_SERVER_MODE");
6468
6476
  } catch {
@@ -6524,10 +6532,11 @@ async function startServer() {
6524
6532
  }
6525
6533
  } catch {
6526
6534
  }
6527
- const selfPath = fileURLToPath3(import.meta.url);
6528
- const spawnCmd = SERVER_SCRIPT === "__self__" ? [process.execPath, selfPath] : [process.execPath, "--import", "tsx", SERVER_SCRIPT];
6535
+ const nodeExec = process.execPath.includes("bun") ? "node" : process.execPath;
6536
+ const selfPath = (0, import_url3.fileURLToPath)(__import_meta_url);
6537
+ const spawnCmd = SERVER_SCRIPT === "__self__" ? [nodeExec, selfPath] : [nodeExec, "--import", "tsx", SERVER_SCRIPT];
6529
6538
  const spawnEnv = { ...process.env, __BROWSE_SERVER_MODE: "1", BROWSE_LOCAL_DIR: LOCAL_DIR3, BROWSE_INSTANCE: BROWSE_INSTANCE2, ...cliFlags.headed ? { BROWSE_HEADED: "1" } : {}, ...cliFlags.cdpUrl ? { BROWSE_CDP_URL: cliFlags.cdpUrl } : {}, ...cliFlags.profile ? { BROWSE_PROFILE: cliFlags.profile } : {} };
6530
- const proc = spawn3(spawnCmd[0], spawnCmd.slice(1), {
6539
+ const proc = (0, import_child_process3.spawn)(spawnCmd[0], spawnCmd.slice(1), {
6531
6540
  stdio: ["ignore", "ignore", "pipe"],
6532
6541
  env: spawnEnv,
6533
6542
  detached: true
@@ -7020,8 +7029,9 @@ if (process.env.__BROWSE_SERVER_MODE === "1") {
7020
7029
  process.exit(1);
7021
7030
  });
7022
7031
  }
7023
- export {
7032
+ // Annotate the CommonJS export names for ESM import in node:
7033
+ 0 && (module.exports = {
7024
7034
  SAFE_TO_RETRY,
7025
7035
  main,
7026
7036
  resolveServerScript
7027
- };
7037
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ulpi/browse",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/ulpi-io/browse"
@@ -14,13 +14,14 @@
14
14
  "playwright-core": "^1.58.2"
15
15
  },
16
16
  "bin": {
17
- "browse": "dist/browse.mjs"
17
+ "browse": "bin/browse"
18
18
  },
19
19
  "description": "Fast headless browser CLI — persistent Chromium daemon via Playwright.",
20
20
  "engines": {
21
21
  "node": ">=18.0.0"
22
22
  },
23
23
  "files": [
24
+ "bin/",
24
25
  "dist/",
25
26
  "skill/",
26
27
  "LICENSE",
@@ -41,7 +42,7 @@
41
42
  "access": "public"
42
43
  },
43
44
  "scripts": {
44
- "build": "esbuild src/cli.ts --bundle --format=esm --platform=node --target=node18 --outfile=dist/browse.mjs --external:playwright --external:playwright-core --external:better-sqlite3 --external:electron --external:chromium-bidi --banner:js='#!/usr/bin/env node'",
45
+ "build": "esbuild src/cli.ts --bundle --format=cjs --platform=node --target=node18 --outfile=dist/browse.cjs --external:playwright --external:playwright-core --external:better-sqlite3 --external:electron --external:chromium-bidi --banner:js='#!/usr/bin/env node\nconst __import_meta_url = require(\"url\").pathToFileURL(__filename).href;' --define:import.meta.url=__import_meta_url",
45
46
  "build:all": "bash scripts/build-all.sh",
46
47
  "dev": "tsx src/cli.ts",
47
48
  "server": "tsx src/server.ts",