unbrowse 6.6.1 → 6.7.0-preview.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.
package/dist/cli.js CHANGED
@@ -31,7 +31,7 @@ var __promiseAll = (args) => Promise.all(args);
31
31
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
32
32
 
33
33
  // ../../src/build-info.generated.ts
34
- var BUILD_RELEASE_VERSION = "6.6.1", BUILD_GIT_SHA = "a3c7f85c4099", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiNi42LjEiLCJnaXRfc2hhIjoiYTNjN2Y4NWM0MDk5IiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUBhM2M3Zjg1YzQwOTkiLCJpc3N1ZWRfYXQiOiIyMDI2LTA1LTA0VDA2OjQ4OjUzLjMwM1oifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "RoWkpJScjvL9xSx7GAwPPi1CvFFWKxuDt2VHYZFlVss", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
34
+ var BUILD_RELEASE_VERSION = "6.7.0-preview.0", BUILD_GIT_SHA = "e73c96e7d7e5", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiNi43LjAtcHJldmlldy4wIiwiZ2l0X3NoYSI6ImU3M2M5NmU3ZDdlNSIsImNvZGVfaGFzaCI6IjVkOWViZjYxOWM2MSIsInRyYWNlX3ZlcnNpb24iOiI1ZDllYmY2MTljNjFAZTczYzk2ZTdkN2U1IiwiaXNzdWVkX2F0IjoiMjAyNi0wNS0wNFQxMToxMToxNS44MTJaIn0", BUILD_RELEASE_MANIFEST_SIGNATURE = "6RTVpC0pvJRHvZPp-HGgkQ08gr0ulga6egVmojNB1vw", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
35
35
 
36
36
  // ../../src/version.ts
37
37
  import { createHash } from "crypto";
@@ -2333,131 +2333,69 @@ var init_telemetry_attribution2 = __esm(() => {
2333
2333
  ];
2334
2334
  });
2335
2335
 
2336
- // ../../src/version.ts
2337
- var exports_version = {};
2338
- __export(exports_version, {
2339
- resolveCodeHashSourceDir: () => resolveCodeHashSourceDir2,
2340
- getPackageVersionForModuleDir: () => getPackageVersionForModuleDir2,
2341
- getEmbeddedReleaseVersion: () => getEmbeddedReleaseVersion2,
2342
- computeCodeHashForDir: () => computeCodeHashForDir2,
2343
- TRACE_VERSION: () => TRACE_VERSION2,
2344
- RELEASE_MANIFEST_SIGNATURE: () => RELEASE_MANIFEST_SIGNATURE2,
2345
- RELEASE_MANIFEST_BASE64: () => RELEASE_MANIFEST_BASE642,
2346
- PACKAGE_VERSION: () => PACKAGE_VERSION2,
2347
- GIT_SHA: () => GIT_SHA2,
2348
- DEFAULT_PROFILE: () => DEFAULT_PROFILE2,
2349
- DEFAULT_BACKEND_URL: () => DEFAULT_BACKEND_URL2,
2350
- CODE_HASH: () => CODE_HASH2
2336
+ // ../../src/sandbox/bundle-replay-client.ts
2337
+ var exports_bundle_replay_client = {};
2338
+ __export(exports_bundle_replay_client, {
2339
+ runBundleReplay: () => runBundleReplay,
2340
+ cookiesToHeaderValue: () => cookiesToHeaderValue,
2341
+ BundleReplayError: () => BundleReplayError
2351
2342
  });
2352
- import { createHash as createHash3 } from "crypto";
2353
- import { existsSync as existsSync17, readFileSync as readFileSync11, readdirSync as readdirSync5 } from "fs";
2354
- import { dirname as dirname4, join as join13, parse as parse2 } from "path";
2355
- import { fileURLToPath as fileURLToPath4 } from "url";
2356
- function collectTsFiles2(dir) {
2357
- const results = [];
2358
- for (const entry of readdirSync5(dir, { withFileTypes: true })) {
2359
- const full = join13(dir, entry.name);
2360
- if (entry.isDirectory() && entry.name !== "node_modules") {
2361
- results.push(...collectTsFiles2(full));
2362
- } else if (entry.name.endsWith(".ts")) {
2363
- results.push(full);
2364
- }
2365
- }
2366
- return results;
2367
- }
2368
- function hashFiles2(srcDir, files) {
2369
- const hash = createHash3("sha256");
2370
- for (const file of files) {
2371
- hash.update(file.slice(srcDir.length));
2372
- hash.update(readFileSync11(file, "utf-8"));
2373
- }
2374
- return hash.digest("hex").slice(0, 12);
2375
- }
2376
- function resolveCodeHashSourceDir2(moduleDir) {
2377
- const candidates = [
2378
- moduleDir,
2379
- join13(moduleDir, "runtime-src"),
2380
- join13(moduleDir, "..", "runtime-src"),
2381
- join13(moduleDir, "src"),
2382
- join13(moduleDir, "..", "src")
2383
- ];
2384
- for (const candidate of candidates) {
2385
- try {
2386
- if (!existsSync17(candidate))
2387
- continue;
2388
- const files = collectTsFiles2(candidate);
2389
- if (files.length > 0)
2390
- return candidate;
2391
- } catch {}
2392
- }
2393
- return null;
2394
- }
2395
- function computeCodeHashForDir2(srcDir) {
2396
- const files = collectTsFiles2(srcDir).sort();
2397
- if (files.length === 0)
2398
- throw new Error(`No TypeScript sources found in ${srcDir}`);
2399
- return hashFiles2(srcDir, files);
2400
- }
2401
- function computeCodeHash2() {
2402
- try {
2403
- const srcDir = resolveCodeHashSourceDir2(MODULE_DIR2);
2404
- if (srcDir)
2405
- return computeCodeHashForDir2(srcDir);
2406
- } catch {}
2407
- const pkgVersion = getPackageVersion2();
2408
- if (pkgVersion !== "unknown") {
2409
- return createHash3("sha256").update(`package:${pkgVersion}`).digest("hex").slice(0, 12);
2343
+ async function runBundleReplay(req, opts = {}) {
2344
+ const base = opts.kuriBase ?? DEFAULT_KURI_BASE;
2345
+ const body = JSON.stringify({
2346
+ target_origin: req.targetOrigin,
2347
+ target_href: req.targetHref,
2348
+ bundle_url: req.bundleUrl,
2349
+ bundle_source: req.bundleSource,
2350
+ fingerprint: req.fingerprint ?? "chrome_mac_arm",
2351
+ impersonate: req.impersonate ?? "chrome131",
2352
+ post_eval: req.postEval,
2353
+ timeout_ms: req.timeoutMs ?? 5000,
2354
+ seed_cookies: req.seedCookies?.map((c) => ({
2355
+ name: c.name,
2356
+ value: c.value,
2357
+ domain: c.domain ?? "",
2358
+ path: c.path ?? "/",
2359
+ secure: c.secure ?? false,
2360
+ http_only: c.http_only ?? c.httpOnly ?? false,
2361
+ same_site: c.same_site ?? c.sameSite ?? "",
2362
+ expires: c.expires ?? 0
2363
+ }))
2364
+ });
2365
+ const resp = await fetch(`${base}/v1/sandbox/replay`, {
2366
+ method: "POST",
2367
+ headers: { "content-type": "application/json" },
2368
+ body,
2369
+ signal: opts.signal
2370
+ });
2371
+ const text = await resp.text();
2372
+ if (!resp.ok) {
2373
+ throw new BundleReplayError(resp.status, text);
2410
2374
  }
2411
- return "compiled";
2412
- }
2413
- function getGitSha2() {
2414
- return BUILD_GIT_SHA?.trim() || "unknown";
2415
- }
2416
- function decodeBase64UrlJson2(value) {
2375
+ let parsed;
2417
2376
  try {
2418
- if (!value)
2419
- return null;
2420
- return JSON.parse(Buffer.from(value, "base64url").toString("utf-8"));
2377
+ parsed = JSON.parse(text);
2421
2378
  } catch {
2422
- return null;
2423
- }
2424
- }
2425
- function getEmbeddedReleaseVersion2() {
2426
- if (BUILD_RELEASE_VERSION?.trim())
2427
- return BUILD_RELEASE_VERSION.trim();
2428
- const manifest = decodeBase64UrlJson2(BUILD_RELEASE_MANIFEST_BASE64?.trim() || "");
2429
- return typeof manifest?.release_version === "string" && manifest.release_version.trim() ? manifest.release_version.trim() : null;
2430
- }
2431
- function getPackageVersionForModuleDir2(moduleDir) {
2432
- let dir = moduleDir;
2433
- const root = parse2(dir).root;
2434
- while (true) {
2435
- try {
2436
- const pkg = JSON.parse(readFileSync11(join13(dir, "package.json"), "utf-8"));
2437
- return typeof pkg.version === "string" ? pkg.version : "unknown";
2438
- } catch {}
2439
- if (dir === root)
2440
- return "unknown";
2441
- dir = dirname4(dir);
2379
+ throw new BundleReplayError(resp.status, `invalid JSON: ${text.slice(0, 200)}`);
2442
2380
  }
2381
+ return parsed;
2443
2382
  }
2444
- function getPackageVersion2() {
2445
- const packageVersion = getPackageVersionForModuleDir2(MODULE_DIR2);
2446
- if (packageVersion !== "unknown")
2447
- return packageVersion;
2448
- return getEmbeddedReleaseVersion2() ?? "unknown";
2383
+ function cookiesToHeaderValue(cookies) {
2384
+ return cookies.map((c) => `${c.name}=${c.value}`).join("; ");
2449
2385
  }
2450
- var MODULE_DIR2, CODE_HASH2, GIT_SHA2, PACKAGE_VERSION2, DEFAULT_BACKEND_URL2, DEFAULT_PROFILE2, TRACE_VERSION2, RELEASE_MANIFEST_BASE642, RELEASE_MANIFEST_SIGNATURE2;
2451
- var init_version2 = __esm(() => {
2452
- MODULE_DIR2 = dirname4(fileURLToPath4(import.meta.url));
2453
- CODE_HASH2 = BUILD_CODE_HASH?.trim() || computeCodeHash2();
2454
- GIT_SHA2 = getGitSha2();
2455
- PACKAGE_VERSION2 = getPackageVersion2();
2456
- DEFAULT_BACKEND_URL2 = BUILD_DEFAULT_BACKEND_URL?.trim() || "https://beta-api.unbrowse.ai";
2457
- DEFAULT_PROFILE2 = BUILD_DEFAULT_PROFILE?.trim() || "";
2458
- TRACE_VERSION2 = `${CODE_HASH2}@${GIT_SHA2}`;
2459
- RELEASE_MANIFEST_BASE642 = BUILD_RELEASE_MANIFEST_BASE64?.trim() || "";
2460
- RELEASE_MANIFEST_SIGNATURE2 = BUILD_RELEASE_MANIFEST_SIGNATURE?.trim() || "";
2386
+ var DEFAULT_KURI_BASE, BundleReplayError;
2387
+ var init_bundle_replay_client = __esm(() => {
2388
+ DEFAULT_KURI_BASE = process.env.KURI_BASE_URL ?? "http://127.0.0.1:6969";
2389
+ BundleReplayError = class BundleReplayError extends Error {
2390
+ status;
2391
+ body;
2392
+ constructor(status, body) {
2393
+ super(`sandbox replay failed: HTTP ${status}: ${body.slice(0, 200)}`);
2394
+ this.status = status;
2395
+ this.body = body;
2396
+ this.name = "BundleReplayError";
2397
+ }
2398
+ };
2461
2399
  });
2462
2400
 
2463
2401
  // ../../src/auth/browser-cookies.ts
@@ -2474,19 +2412,19 @@ __export(exports_browser_cookies2, {
2474
2412
  });
2475
2413
  import { execFileSync as execFileSync5 } from "node:child_process";
2476
2414
  import { createDecipheriv as createDecipheriv3, pbkdf2Sync as pbkdf2Sync2 } from "node:crypto";
2477
- import { copyFileSync as copyFileSync2, existsSync as existsSync18, mkdtempSync as mkdtempSync2, readdirSync as readdirSync6, rmSync as rmSync2 } from "node:fs";
2415
+ import { copyFileSync as copyFileSync2, existsSync as existsSync17, mkdtempSync as mkdtempSync2, readdirSync as readdirSync5, rmSync as rmSync2 } from "node:fs";
2478
2416
  import { tmpdir as tmpdir2, homedir as homedir8, platform as platform2 } from "node:os";
2479
- import { join as join14 } from "node:path";
2417
+ import { join as join13 } from "node:path";
2480
2418
  function getChromeUserDataDir2() {
2481
2419
  const home = homedir8();
2482
2420
  if (platform2() === "darwin") {
2483
- return join14(home, "Library", "Application Support", "Google", "Chrome");
2421
+ return join13(home, "Library", "Application Support", "Google", "Chrome");
2484
2422
  }
2485
2423
  if (platform2() === "win32") {
2486
- const appData = process.env.LOCALAPPDATA ?? join14(home, "AppData", "Local");
2487
- return join14(appData, "Google", "Chrome", "User Data");
2424
+ const appData = process.env.LOCALAPPDATA ?? join13(home, "AppData", "Local");
2425
+ return join13(appData, "Google", "Chrome", "User Data");
2488
2426
  }
2489
- return join14(home, ".config", "google-chrome");
2427
+ return join13(home, ".config", "google-chrome");
2490
2428
  }
2491
2429
  function resolveChromiumCookiesPath2(opts) {
2492
2430
  if (opts?.cookieDbPath) {
@@ -2495,45 +2433,45 @@ function resolveChromiumCookiesPath2(opts) {
2495
2433
  const profileDir = opts?.profile || "Default";
2496
2434
  const userDataDir = (opts?.userDataDir || getChromeUserDataDir2()).replace(/^~\//, homedir8() + "/");
2497
2435
  const candidates = [
2498
- join14(userDataDir, profileDir, "Network", "Cookies"),
2499
- join14(userDataDir, profileDir, "Cookies"),
2500
- join14(userDataDir, "Network", "Cookies"),
2501
- join14(userDataDir, "Cookies")
2436
+ join13(userDataDir, profileDir, "Network", "Cookies"),
2437
+ join13(userDataDir, profileDir, "Cookies"),
2438
+ join13(userDataDir, "Network", "Cookies"),
2439
+ join13(userDataDir, "Cookies")
2502
2440
  ];
2503
- return candidates.find((candidate) => existsSync18(candidate)) ?? candidates[0] ?? null;
2441
+ return candidates.find((candidate) => existsSync17(candidate)) ?? candidates[0] ?? null;
2504
2442
  }
2505
2443
  function getFirefoxProfilesRoot2() {
2506
2444
  const home = homedir8();
2507
2445
  if (platform2() === "darwin") {
2508
- return join14(home, "Library", "Application Support", "Firefox", "Profiles");
2446
+ return join13(home, "Library", "Application Support", "Firefox", "Profiles");
2509
2447
  }
2510
2448
  if (platform2() === "linux") {
2511
- return join14(home, ".mozilla", "firefox");
2449
+ return join13(home, ".mozilla", "firefox");
2512
2450
  }
2513
2451
  if (platform2() === "win32") {
2514
2452
  const appData = process.env.APPDATA;
2515
2453
  if (!appData)
2516
2454
  return null;
2517
- return join14(appData, "Mozilla", "Firefox", "Profiles");
2455
+ return join13(appData, "Mozilla", "Firefox", "Profiles");
2518
2456
  }
2519
2457
  return null;
2520
2458
  }
2521
2459
  function pickFirefoxProfile2(profilesRoot, profile) {
2522
2460
  if (profile) {
2523
- const candidate2 = join14(profilesRoot, profile, "cookies.sqlite");
2524
- return existsSync18(candidate2) ? candidate2 : null;
2461
+ const candidate2 = join13(profilesRoot, profile, "cookies.sqlite");
2462
+ return existsSync17(candidate2) ? candidate2 : null;
2525
2463
  }
2526
- const entries = readdirSync6(profilesRoot, { withFileTypes: true });
2464
+ const entries = readdirSync5(profilesRoot, { withFileTypes: true });
2527
2465
  const defaultRelease = entries.find((e) => e.isDirectory() && e.name.includes("default-release"));
2528
2466
  const targetDir = defaultRelease?.name ?? entries.find((e) => e.isDirectory())?.name;
2529
2467
  if (!targetDir)
2530
2468
  return null;
2531
- const candidate = join14(profilesRoot, targetDir, "cookies.sqlite");
2532
- return existsSync18(candidate) ? candidate : null;
2469
+ const candidate = join13(profilesRoot, targetDir, "cookies.sqlite");
2470
+ return existsSync17(candidate) ? candidate : null;
2533
2471
  }
2534
2472
  function getFirefoxCookiesPath2(profile) {
2535
2473
  const profilesRoot = getFirefoxProfilesRoot2();
2536
- if (!profilesRoot || !existsSync18(profilesRoot))
2474
+ if (!profilesRoot || !existsSync17(profilesRoot))
2537
2475
  return null;
2538
2476
  return pickFirefoxProfile2(profilesRoot, profile);
2539
2477
  }
@@ -2602,13 +2540,13 @@ function decodeChromiumCookieValue2(rawValue, encryptedHex, opts) {
2602
2540
  return decryptChromiumValue2(encryptedHex, opts);
2603
2541
  }
2604
2542
  function withTempCopy2(dbPath, fn) {
2605
- const tempDir = mkdtempSync2(join14(tmpdir2(), "unbrowse-cookies-"));
2606
- const tempDb = join14(tempDir, "cookies.db");
2543
+ const tempDir = mkdtempSync2(join13(tmpdir2(), "unbrowse-cookies-"));
2544
+ const tempDb = join13(tempDir, "cookies.db");
2607
2545
  try {
2608
2546
  copyFileSync2(dbPath, tempDb);
2609
2547
  for (const ext of ["-wal", "-shm"]) {
2610
2548
  const src = dbPath + ext;
2611
- if (existsSync18(src))
2549
+ if (existsSync17(src))
2612
2550
  copyFileSync2(src, tempDb + ext);
2613
2551
  }
2614
2552
  return fn(tempDb);
@@ -2653,7 +2591,7 @@ function extractFromChromium2(domain, opts) {
2653
2591
  const warnings = [];
2654
2592
  const dbPath = resolveChromiumCookiesPath2(opts);
2655
2593
  const sourceLabel = opts?.browserName || "Chromium";
2656
- if (!dbPath || !existsSync18(dbPath)) {
2594
+ if (!dbPath || !existsSync17(dbPath)) {
2657
2595
  warnings.push(`${sourceLabel} cookies DB not found${dbPath ? ` at ${dbPath}` : ""}`);
2658
2596
  return { cookies: [], source: null, warnings };
2659
2597
  }
@@ -2748,8 +2686,8 @@ function extractFromFirefox2(domain, opts) {
2748
2686
  function extractBrowserCookies2(domain, opts) {
2749
2687
  const __result = _extractBrowserCookiesInner2(domain, opts);
2750
2688
  try {
2751
- const traceDir = join14(homedir8(), ".unbrowse", "traces");
2752
- if (!existsSync18(traceDir))
2689
+ const traceDir = join13(homedir8(), ".unbrowse", "traces");
2690
+ if (!existsSync17(traceDir))
2753
2691
  mkdirSync(traceDir, { recursive: true });
2754
2692
  const entry = JSON.stringify({
2755
2693
  d: domain,
@@ -2758,7 +2696,7 @@ function extractBrowserCookies2(domain, opts) {
2758
2696
  c: __result.cookies.map((c) => ({ n: c.name, v: c.value, d: c.domain }))
2759
2697
  }) + `
2760
2698
  `;
2761
- writeFileSync(join14(traceDir, "auth-extract.jsonl"), entry, { flag: "a" });
2699
+ writeFileSync(join13(traceDir, "auth-extract.jsonl"), entry, { flag: "a" });
2762
2700
  } catch {}
2763
2701
  return __result;
2764
2702
  }
@@ -2802,8 +2740,8 @@ function scanAllBrowserSessions2(domain) {
2802
2740
  const results = [];
2803
2741
  const home = homedir8();
2804
2742
  for (const browser of CHROMIUM_BROWSERS2) {
2805
- const userDataDir = platform2() === "darwin" ? join14(home, "Library", "Application Support", browser.macPath) : platform2() === "win32" ? join14(process.env.LOCALAPPDATA ?? join14(home, "AppData", "Local"), browser.macPath, "User Data") : join14(home, ".config", browser.macPath.toLowerCase());
2806
- if (!existsSync18(userDataDir))
2743
+ const userDataDir = platform2() === "darwin" ? join13(home, "Library", "Application Support", browser.macPath) : platform2() === "win32" ? join13(process.env.LOCALAPPDATA ?? join13(home, "AppData", "Local"), browser.macPath, "User Data") : join13(home, ".config", browser.macPath.toLowerCase());
2744
+ if (!existsSync17(userDataDir))
2807
2745
  continue;
2808
2746
  try {
2809
2747
  const result = extractFromChromium2(domain, {
@@ -2857,6 +2795,133 @@ var init_browser_cookies2 = __esm(() => {
2857
2795
  ];
2858
2796
  });
2859
2797
 
2798
+ // ../../src/version.ts
2799
+ var exports_version = {};
2800
+ __export(exports_version, {
2801
+ resolveCodeHashSourceDir: () => resolveCodeHashSourceDir2,
2802
+ getPackageVersionForModuleDir: () => getPackageVersionForModuleDir2,
2803
+ getEmbeddedReleaseVersion: () => getEmbeddedReleaseVersion2,
2804
+ computeCodeHashForDir: () => computeCodeHashForDir2,
2805
+ TRACE_VERSION: () => TRACE_VERSION2,
2806
+ RELEASE_MANIFEST_SIGNATURE: () => RELEASE_MANIFEST_SIGNATURE2,
2807
+ RELEASE_MANIFEST_BASE64: () => RELEASE_MANIFEST_BASE642,
2808
+ PACKAGE_VERSION: () => PACKAGE_VERSION2,
2809
+ GIT_SHA: () => GIT_SHA2,
2810
+ DEFAULT_PROFILE: () => DEFAULT_PROFILE2,
2811
+ DEFAULT_BACKEND_URL: () => DEFAULT_BACKEND_URL2,
2812
+ CODE_HASH: () => CODE_HASH2
2813
+ });
2814
+ import { createHash as createHash3 } from "crypto";
2815
+ import { existsSync as existsSync18, readFileSync as readFileSync11, readdirSync as readdirSync6 } from "fs";
2816
+ import { dirname as dirname4, join as join14, parse as parse2 } from "path";
2817
+ import { fileURLToPath as fileURLToPath4 } from "url";
2818
+ function collectTsFiles2(dir) {
2819
+ const results = [];
2820
+ for (const entry of readdirSync6(dir, { withFileTypes: true })) {
2821
+ const full = join14(dir, entry.name);
2822
+ if (entry.isDirectory() && entry.name !== "node_modules") {
2823
+ results.push(...collectTsFiles2(full));
2824
+ } else if (entry.name.endsWith(".ts")) {
2825
+ results.push(full);
2826
+ }
2827
+ }
2828
+ return results;
2829
+ }
2830
+ function hashFiles2(srcDir, files) {
2831
+ const hash = createHash3("sha256");
2832
+ for (const file of files) {
2833
+ hash.update(file.slice(srcDir.length));
2834
+ hash.update(readFileSync11(file, "utf-8"));
2835
+ }
2836
+ return hash.digest("hex").slice(0, 12);
2837
+ }
2838
+ function resolveCodeHashSourceDir2(moduleDir) {
2839
+ const candidates = [
2840
+ moduleDir,
2841
+ join14(moduleDir, "runtime-src"),
2842
+ join14(moduleDir, "..", "runtime-src"),
2843
+ join14(moduleDir, "src"),
2844
+ join14(moduleDir, "..", "src")
2845
+ ];
2846
+ for (const candidate of candidates) {
2847
+ try {
2848
+ if (!existsSync18(candidate))
2849
+ continue;
2850
+ const files = collectTsFiles2(candidate);
2851
+ if (files.length > 0)
2852
+ return candidate;
2853
+ } catch {}
2854
+ }
2855
+ return null;
2856
+ }
2857
+ function computeCodeHashForDir2(srcDir) {
2858
+ const files = collectTsFiles2(srcDir).sort();
2859
+ if (files.length === 0)
2860
+ throw new Error(`No TypeScript sources found in ${srcDir}`);
2861
+ return hashFiles2(srcDir, files);
2862
+ }
2863
+ function computeCodeHash2() {
2864
+ try {
2865
+ const srcDir = resolveCodeHashSourceDir2(MODULE_DIR2);
2866
+ if (srcDir)
2867
+ return computeCodeHashForDir2(srcDir);
2868
+ } catch {}
2869
+ const pkgVersion = getPackageVersion2();
2870
+ if (pkgVersion !== "unknown") {
2871
+ return createHash3("sha256").update(`package:${pkgVersion}`).digest("hex").slice(0, 12);
2872
+ }
2873
+ return "compiled";
2874
+ }
2875
+ function getGitSha2() {
2876
+ return BUILD_GIT_SHA?.trim() || "unknown";
2877
+ }
2878
+ function decodeBase64UrlJson2(value) {
2879
+ try {
2880
+ if (!value)
2881
+ return null;
2882
+ return JSON.parse(Buffer.from(value, "base64url").toString("utf-8"));
2883
+ } catch {
2884
+ return null;
2885
+ }
2886
+ }
2887
+ function getEmbeddedReleaseVersion2() {
2888
+ if (BUILD_RELEASE_VERSION?.trim())
2889
+ return BUILD_RELEASE_VERSION.trim();
2890
+ const manifest = decodeBase64UrlJson2(BUILD_RELEASE_MANIFEST_BASE64?.trim() || "");
2891
+ return typeof manifest?.release_version === "string" && manifest.release_version.trim() ? manifest.release_version.trim() : null;
2892
+ }
2893
+ function getPackageVersionForModuleDir2(moduleDir) {
2894
+ let dir = moduleDir;
2895
+ const root = parse2(dir).root;
2896
+ while (true) {
2897
+ try {
2898
+ const pkg = JSON.parse(readFileSync11(join14(dir, "package.json"), "utf-8"));
2899
+ return typeof pkg.version === "string" ? pkg.version : "unknown";
2900
+ } catch {}
2901
+ if (dir === root)
2902
+ return "unknown";
2903
+ dir = dirname4(dir);
2904
+ }
2905
+ }
2906
+ function getPackageVersion2() {
2907
+ const packageVersion = getPackageVersionForModuleDir2(MODULE_DIR2);
2908
+ if (packageVersion !== "unknown")
2909
+ return packageVersion;
2910
+ return getEmbeddedReleaseVersion2() ?? "unknown";
2911
+ }
2912
+ var MODULE_DIR2, CODE_HASH2, GIT_SHA2, PACKAGE_VERSION2, DEFAULT_BACKEND_URL2, DEFAULT_PROFILE2, TRACE_VERSION2, RELEASE_MANIFEST_BASE642, RELEASE_MANIFEST_SIGNATURE2;
2913
+ var init_version2 = __esm(() => {
2914
+ MODULE_DIR2 = dirname4(fileURLToPath4(import.meta.url));
2915
+ CODE_HASH2 = BUILD_CODE_HASH?.trim() || computeCodeHash2();
2916
+ GIT_SHA2 = getGitSha2();
2917
+ PACKAGE_VERSION2 = getPackageVersion2();
2918
+ DEFAULT_BACKEND_URL2 = BUILD_DEFAULT_BACKEND_URL?.trim() || "https://beta-api.unbrowse.ai";
2919
+ DEFAULT_PROFILE2 = BUILD_DEFAULT_PROFILE?.trim() || "";
2920
+ TRACE_VERSION2 = `${CODE_HASH2}@${GIT_SHA2}`;
2921
+ RELEASE_MANIFEST_BASE642 = BUILD_RELEASE_MANIFEST_BASE64?.trim() || "";
2922
+ RELEASE_MANIFEST_SIGNATURE2 = BUILD_RELEASE_MANIFEST_SIGNATURE?.trim() || "";
2923
+ });
2924
+
2860
2925
  // ../../src/cli.ts
2861
2926
  import { config as loadEnv } from "dotenv";
2862
2927
  import { spawn as spawn3 } from "child_process";
@@ -5067,7 +5132,17 @@ function parseArgs(argv) {
5067
5132
  "form-selector",
5068
5133
  "submit-selector",
5069
5134
  "wait-for",
5070
- "timeout-ms"
5135
+ "timeout-ms",
5136
+ "target-origin",
5137
+ "target-href",
5138
+ "bundle-url",
5139
+ "bundle-source",
5140
+ "post-eval",
5141
+ "fingerprint",
5142
+ "impersonate",
5143
+ "origin",
5144
+ "bundle",
5145
+ "eval"
5071
5146
  ]);
5072
5147
  if (valueExpectedFlags.has(key)) {
5073
5148
  if (next === undefined)
@@ -6329,6 +6404,72 @@ async function cmdNote(flags, args) {
6329
6404
  const res = await api2("POST", `/v1/domain-notes/${encodeURIComponent(domain)}`, { body });
6330
6405
  output(res, !!flags.pretty);
6331
6406
  }
6407
+ async function cmdSandboxReplay(args, flags) {
6408
+ const { runBundleReplay: runBundleReplay2, cookiesToHeaderValue: cookiesToHeaderValue2 } = await Promise.resolve().then(() => (init_bundle_replay_client(), exports_bundle_replay_client));
6409
+ const targetOrigin = flags["target-origin"] ?? flags.origin;
6410
+ const targetHref = flags["target-href"] ?? flags.url;
6411
+ const bundleUrl = flags["bundle-url"] ?? flags.bundle;
6412
+ let bundleSource = flags["bundle-source"];
6413
+ const postEval = flags["post-eval"] ?? flags.eval;
6414
+ const fingerprint = flags.fingerprint ?? "chrome_mac_arm";
6415
+ const impersonate = flags.impersonate ?? "chrome131";
6416
+ const timeoutMs = flags["timeout-ms"] ? Number(flags["timeout-ms"]) : 5000;
6417
+ if (bundleSource === "-" || flags["stdin"]) {
6418
+ const chunks = [];
6419
+ for await (const c of process.stdin)
6420
+ chunks.push(c);
6421
+ bundleSource = Buffer.concat(chunks).toString("utf8");
6422
+ }
6423
+ if (!targetOrigin)
6424
+ die("usage: unbrowse sandbox-replay --target-origin <url> [--target-href <url>] (--bundle-url <url> | --bundle-source <js|->) [--post-eval <expr>]");
6425
+ if (!bundleUrl && !bundleSource)
6426
+ die("--bundle-url or --bundle-source required");
6427
+ const kuriBase = process.env.KURI_BASE_URL ?? "http://127.0.0.1:8080";
6428
+ try {
6429
+ const h = await fetch(`${kuriBase}/health`, { signal: AbortSignal.timeout(2000) });
6430
+ if (!h.ok)
6431
+ die(`Kuri health check failed (HTTP ${h.status}). Start kuri first.`);
6432
+ } catch (e) {
6433
+ die(`Kuri unreachable at ${kuriBase}: ${e.message}. Run: submodules/kuri/zig-out/bin/kuri`);
6434
+ }
6435
+ let seedCookies;
6436
+ if (flags["use-browser-cookies"]) {
6437
+ const { findBestBrowserSession: findBestBrowserSession3 } = await Promise.resolve().then(() => (init_browser_cookies2(), exports_browser_cookies2));
6438
+ const host = (() => {
6439
+ try {
6440
+ return new URL(targetOrigin).hostname;
6441
+ } catch {
6442
+ return targetOrigin;
6443
+ }
6444
+ })();
6445
+ const session = findBestBrowserSession3(host);
6446
+ if (session) {
6447
+ seedCookies = session.cookies;
6448
+ info(`[sandbox-replay] seeded ${session.cookies.length} cookies from ${session.browser} (${session.sessionCookies} httpOnly+secure)`);
6449
+ } else {
6450
+ info(`[sandbox-replay] --use-browser-cookies: no logged-in session found for ${host} across Chrome/Arc/Brave/Edge/Vivaldi/Opera/Dia/Chromium`);
6451
+ }
6452
+ }
6453
+ const resp = await runBundleReplay2({
6454
+ targetOrigin,
6455
+ targetHref,
6456
+ bundleUrl,
6457
+ bundleSource,
6458
+ fingerprint,
6459
+ impersonate,
6460
+ postEval,
6461
+ timeoutMs,
6462
+ seedCookies
6463
+ }, { kuriBase: process.env.KURI_BASE_URL ?? "http://127.0.0.1:8080" });
6464
+ output({
6465
+ ok: resp.ok,
6466
+ ms: resp.ms,
6467
+ egress_bytes: resp.egress_bytes,
6468
+ cookies: resp.cookies,
6469
+ cookie_header: cookiesToHeaderValue2(resp.cookies),
6470
+ post_eval: resp.post_eval
6471
+ }, !!flags.pretty);
6472
+ }
6332
6473
  var CLI_REFERENCE = {
6333
6474
  commands: [
6334
6475
  { name: "health", usage: "", desc: "Server health check" },
@@ -6379,7 +6520,8 @@ var CLI_REFERENCE = {
6379
6520
  { name: "dashboard", usage: "[--no-open] [--pretty]", desc: "Open the website dashboard and pair it to this CLI install through localhost" },
6380
6521
  { name: "mode", usage: "", desc: "Re-prompt for contribution mode (private / share / share + earn)" },
6381
6522
  { name: "capture", usage: "--url <url> --intent <intent>", desc: "Live-browser capture for a single URL \u2014 discovers + indexes API endpoints. Marketplace publish gated by `unbrowse mode`." },
6382
- { name: "note", usage: '<read|write|list> --domain <domain> [--body "..."]', desc: "Read/write per-domain LLM-prose notes consumed by augment on next capture. Agent populates after reading capture's note_evidence." }
6523
+ { name: "note", usage: '<read|write|list> --domain <domain> [--body "..."]', desc: "Read/write per-domain LLM-prose notes consumed by augment on next capture. Agent populates after reading capture's note_evidence." },
6524
+ { name: "sandbox-replay", usage: "--target-origin <url> [--target-href <url>] [--bundle-url <url> | --bundle-source <js|->] [--post-eval <expr>] [--use-browser-cookies]", desc: "Run an anti-bot / signed-URL / HMAC bundle in Kuri's sandboxed JS runtime (QuickJS + statically-linked libcurl-impersonate, real Chrome 131 JA4). Returns harvested cookies + optional postEval result. --use-browser-cookies seeds the jar from the user's Chrome/Arc/Brave/Edge/Vivaldi/Opera/Dia session." }
6383
6525
  ],
6384
6526
  globalFlags: [
6385
6527
  { flag: "--pretty", desc: "Indented JSON output" },
@@ -7604,6 +7746,8 @@ async function main() {
7604
7746
  return cmdCapture(flags);
7605
7747
  case "note":
7606
7748
  return cmdNote(flags, args);
7749
+ case "sandbox-replay":
7750
+ return cmdSandboxReplay(args, flags);
7607
7751
  default:
7608
7752
  info(`Unknown command: ${command}`);
7609
7753
  printHelp();
package/dist/mcp.js CHANGED
@@ -226,11 +226,11 @@ import { dirname, join, parse } from "path";
226
226
  import { fileURLToPath as fileURLToPath2 } from "url";
227
227
 
228
228
  // ../../src/build-info.generated.ts
229
- var BUILD_RELEASE_VERSION = "6.6.1";
230
- var BUILD_GIT_SHA = "a3c7f85c4099";
229
+ var BUILD_RELEASE_VERSION = "6.7.0-preview.0";
230
+ var BUILD_GIT_SHA = "e73c96e7d7e5";
231
231
  var BUILD_CODE_HASH = "5d9ebf619c61";
232
- var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiNi42LjEiLCJnaXRfc2hhIjoiYTNjN2Y4NWM0MDk5IiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUBhM2M3Zjg1YzQwOTkiLCJpc3N1ZWRfYXQiOiIyMDI2LTA1LTA0VDA2OjQ4OjUzLjMwM1oifQ";
233
- var BUILD_RELEASE_MANIFEST_SIGNATURE = "RoWkpJScjvL9xSx7GAwPPi1CvFFWKxuDt2VHYZFlVss";
232
+ var BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiNi43LjAtcHJldmlldy4wIiwiZ2l0X3NoYSI6ImU3M2M5NmU3ZDdlNSIsImNvZGVfaGFzaCI6IjVkOWViZjYxOWM2MSIsInRyYWNlX3ZlcnNpb24iOiI1ZDllYmY2MTljNjFAZTczYzk2ZTdkN2U1IiwiaXNzdWVkX2F0IjoiMjAyNi0wNS0wNFQxMToxMToxNS44MTJaIn0";
233
+ var BUILD_RELEASE_MANIFEST_SIGNATURE = "6RTVpC0pvJRHvZPp-HGgkQ08gr0ulga6egVmojNB1vw";
234
234
  var BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai";
235
235
  var BUILD_DEFAULT_PROFILE = "";
236
236
 
package/dist/server.js CHANGED
@@ -7342,7 +7342,7 @@ var init_capture = __esm(async () => {
7342
7342
  });
7343
7343
 
7344
7344
  // ../../src/build-info.generated.ts
7345
- var BUILD_RELEASE_VERSION = "6.6.1", BUILD_GIT_SHA = "a3c7f85c4099", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiNi42LjEiLCJnaXRfc2hhIjoiYTNjN2Y4NWM0MDk5IiwiY29kZV9oYXNoIjoiNWQ5ZWJmNjE5YzYxIiwidHJhY2VfdmVyc2lvbiI6IjVkOWViZjYxOWM2MUBhM2M3Zjg1YzQwOTkiLCJpc3N1ZWRfYXQiOiIyMDI2LTA1LTA0VDA2OjQ4OjUzLjMwM1oifQ", BUILD_RELEASE_MANIFEST_SIGNATURE = "RoWkpJScjvL9xSx7GAwPPi1CvFFWKxuDt2VHYZFlVss", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
7345
+ var BUILD_RELEASE_VERSION = "6.7.0-preview.0", BUILD_GIT_SHA = "e73c96e7d7e5", BUILD_CODE_HASH = "5d9ebf619c61", BUILD_RELEASE_MANIFEST_BASE64 = "eyJzY2hlbWFfdmVyc2lvbiI6MSwicmVsZWFzZV92ZXJzaW9uIjoiNi43LjAtcHJldmlldy4wIiwiZ2l0X3NoYSI6ImU3M2M5NmU3ZDdlNSIsImNvZGVfaGFzaCI6IjVkOWViZjYxOWM2MSIsInRyYWNlX3ZlcnNpb24iOiI1ZDllYmY2MTljNjFAZTczYzk2ZTdkN2U1IiwiaXNzdWVkX2F0IjoiMjAyNi0wNS0wNFQxMToxMToxNS44MTJaIn0", BUILD_RELEASE_MANIFEST_SIGNATURE = "6RTVpC0pvJRHvZPp-HGgkQ08gr0ulga6egVmojNB1vw", BUILD_DEFAULT_BACKEND_URL = "https://beta-api.unbrowse.ai", BUILD_DEFAULT_PROFILE = "";
7346
7346
 
7347
7347
  // ../../src/version.ts
7348
7348
  import { createHash as createHash2 } from "crypto";
@@ -16102,6 +16102,7 @@ __export(exports_execution, {
16102
16102
  projectResultForIntent: () => projectResultForIntent,
16103
16103
  matchResponseSignal: () => matchResponseSignal,
16104
16104
  isBundleInferredEndpoint: () => isBundleInferredEndpoint,
16105
+ extractBundleSnapshot: () => extractBundleSnapshot,
16105
16106
  executeSkill: () => executeSkill,
16106
16107
  executeEndpoint: () => executeEndpoint,
16107
16108
  detectBrowserBlockSignals: () => detectBrowserBlockSignals,
@@ -16855,12 +16856,25 @@ async function executeBrowserCapture(skill, params, options) {
16855
16856
  rejectedSamples.push({ url: u, reason });
16856
16857
  }
16857
16858
  const apiCallCount = captured.requests?.length ?? 0;
16859
+ const requestUrls = (captured.requests ?? []).map((r) => r.url ?? "");
16858
16860
  const blockSignals = detectBrowserBlockSignals({
16859
- requestUrls: (captured.requests ?? []).map((r) => r.url ?? ""),
16861
+ requestUrls,
16860
16862
  title,
16861
16863
  htmlLength: html.length,
16862
16864
  rejectionCounts
16863
16865
  });
16866
+ const bundleSnapshot = extractBundleSnapshot({
16867
+ requestUrls,
16868
+ blockSignals,
16869
+ targetOrigin: (() => {
16870
+ try {
16871
+ return new URL(url).origin;
16872
+ } catch {
16873
+ return url;
16874
+ }
16875
+ })(),
16876
+ targetHref: url
16877
+ });
16864
16878
  return {
16865
16879
  html_bytes: html.length,
16866
16880
  title,
@@ -16870,7 +16884,8 @@ async function executeBrowserCapture(skill, params, options) {
16870
16884
  intent_reason: intentReason,
16871
16885
  filter_rejections: rejectionCounts,
16872
16886
  rejected_samples: rejectedSamples,
16873
- browser_block_signals: blockSignals
16887
+ browser_block_signals: blockSignals,
16888
+ ...bundleSnapshot ? { bundle_snapshot: bundleSnapshot } : {}
16874
16889
  };
16875
16890
  };
16876
16891
  if (captured.html) {
@@ -18500,6 +18515,47 @@ function detectBrowserBlockSignals(input) {
18500
18515
  }
18501
18516
  return signals;
18502
18517
  }
18518
+ function extractBundleSnapshot(input) {
18519
+ const { requestUrls, blockSignals, targetOrigin, targetHref } = input;
18520
+ const vendor = blockSignals.find((s) => s.startsWith("vendor:"))?.slice("vendor:".length);
18521
+ if (!vendor)
18522
+ return null;
18523
+ const matchers = {
18524
+ perimeterx: [
18525
+ /perimeterx|px-cloud|px-cdn|pxhd\.net/i,
18526
+ /KP_UIDz=/,
18527
+ /\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/(ips\.js|tl|xhr|init)/i
18528
+ ],
18529
+ datadome: [/datadome|js\.datadome|dd\.datadome|_dd\.s|ddjskey/i],
18530
+ imperva_incapsula: [/akamaihd|ak-challenge|_Incapsula|incapsula|reese84/i],
18531
+ akamai_bot_manager: [/akam\.net|bot-defender|\/_bm\/|sensor[-_]data|bm\.nuid|_abck/i],
18532
+ cloudflare: [/cf-challenge|__cf_chl_|turnstile|challenges\.cloudflare/i],
18533
+ fastly_bot_management: [/\/_fs-ch-[A-Za-z0-9]+\//],
18534
+ captcha_vendor: [/hcaptcha|recaptcha|arkoselabs|funcaptcha/i],
18535
+ shape_security: [/shape\.security|f5\.com\/shape|ShapeSecurity/i],
18536
+ kasada: [/kasada|client\.kasada|ips\.kasada/i]
18537
+ };
18538
+ const patterns = matchers[vendor] ?? [];
18539
+ const matched = requestUrls.filter((u) => patterns.some((p) => p.test(u)));
18540
+ const bundleUrls = [];
18541
+ const cookieIssuingUrls = [];
18542
+ for (const u of matched) {
18543
+ if (/\.js(\?|$|#)/i.test(u) || /ips\.js/i.test(u))
18544
+ bundleUrls.push(u);
18545
+ else
18546
+ cookieIssuingUrls.push(u);
18547
+ }
18548
+ if (bundleUrls.length === 0 && cookieIssuingUrls.length === 0)
18549
+ return null;
18550
+ return {
18551
+ vendor,
18552
+ bundle_urls: bundleUrls,
18553
+ cookie_issuing_urls: cookieIssuingUrls,
18554
+ target_origin: targetOrigin,
18555
+ target_href: targetHref,
18556
+ captured_at: Math.floor(Date.now() / 1000)
18557
+ };
18558
+ }
18503
18559
  function decomposeGraphqlEndpoint(endpoint) {
18504
18560
  const url = endpoint.url_template ?? "";
18505
18561
  const looksGraphql = /\/graphql\//i.test(url) || /\bvariables=\{variables\}/.test(url) || Array.isArray(endpoint.semantic?.requires) && endpoint.semantic.requires.some((r) => r.key === "variables") && endpoint.semantic.requires.some((r) => r.key === "features");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unbrowse",
3
- "version": "6.6.1",
3
+ "version": "6.7.0-preview.0",
4
4
  "description": "Reverse-engineer any website into reusable API skills. Zero-dep single binary with embedded browser engine.",
5
5
  "type": "module",
6
6
  "bin": {
Binary file
Binary file
Binary file
Binary file
@@ -1,24 +1,28 @@
1
1
  {
2
2
  "repo_url": "https://github.com/justrach/kuri.git",
3
3
  "branch": "adding-extensions",
4
- "source_sha": "b91acae982e7d4f1d991dc4cf3e8340176e1787b",
5
- "built_at": "2026-05-03T07:34:48.688Z",
4
+ "source_sha": "48fe847959d76420ee35b6ad004c841831d35455",
5
+ "built_at": "2026-05-04T11:06:18.067Z",
6
6
  "binaries": {
7
7
  "darwin-arm64": {
8
8
  "zig_target": "aarch64-macos",
9
- "sha256": "d4336848294c404f1daa1b5d579939a0547a141efaf15ec6c312c27a61fa331f"
9
+ "source": "placeholder",
10
+ "sha256": "ca459cd22baadb02a3e246c547e39a2b9a3eccc2b50852b5a05386b3c584c760"
10
11
  },
11
12
  "darwin-x64": {
12
13
  "zig_target": "x86_64-macos",
13
- "sha256": "cfc3a34214db4c79fa11eae03162271094b74c29f72e93ebab987ec89765dc76"
14
+ "source": "placeholder",
15
+ "sha256": "05b88578d5e7980d81e18ba3051c813271d1630d940009a599c791956090d122"
14
16
  },
15
17
  "linux-arm64": {
16
18
  "zig_target": "aarch64-linux",
17
- "sha256": "637fd85c251493e472a6cae5fccc518b4144ecd5a38c3cfe52fa22f0ad5f2734"
19
+ "source": "placeholder",
20
+ "sha256": "6a47890b281c8178a5df040cbaf1e32acd9ddf1eb23428055e1a3abce79f92e5"
18
21
  },
19
22
  "linux-x64": {
20
23
  "zig_target": "x86_64-linux",
21
- "sha256": "e68635c799012883e937e28c7b4aa1401e84bd3d8d6d1f22cb85bf836f5a4dc4"
24
+ "source": "placeholder",
25
+ "sha256": "66e35d14361feb683b80dc7e01902a454945ce6829dbb31ed99c1751abc9ced8"
22
26
  }
23
27
  }
24
28
  }