@vibetechnologies/chrome-sync 0.4.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/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # @vibetechnologies/browser-sync
2
+
3
+ Sync browser cookies and sessions from your local Chrome to your OpenClaw cloud browser.
4
+
5
+ ## Why
6
+
7
+ Cloud browsers can't log into Google, GitHub, or other sites that detect automation. Instead of fighting detection, bring your existing authenticated session to the cloud.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install -g @vibetechnologies/browser-sync
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### 1. Authenticate
18
+
19
+ ```bash
20
+ browser-sync login --token <your-api-token>
21
+ ```
22
+
23
+ ### 2. Push cookies to cloud browser
24
+
25
+ ```bash
26
+ # Sync Google cookies
27
+ browser-sync push --domains google.com,gmail.com
28
+
29
+ # Sync multiple services
30
+ browser-sync push --domains google.com,github.com,linkedin.com
31
+
32
+ # Use a specific Chrome profile
33
+ browser-sync push --domains google.com --profile "Profile 1"
34
+
35
+ # Dry run — see what would be synced
36
+ browser-sync push --domains google.com --dry-run
37
+ ```
38
+
39
+ ### 3. List Chrome profiles
40
+
41
+ ```bash
42
+ browser-sync profiles
43
+ ```
44
+
45
+ ## How it works
46
+
47
+ 1. Reads and decrypts cookies from your local Chrome cookie database
48
+ 2. Sends them (encrypted in transit) to the OpenClaw API
49
+ 3. Server injects cookies into your tenant's cloud Chrome via CDP `Network.setCookies`
50
+ 4. Your cloud browser now has your authenticated sessions
51
+
52
+ ## Supported platforms
53
+
54
+ | OS | Cookie decryption |
55
+ |----|-------------------|
56
+ | macOS | Keychain → AES-128-CBC |
57
+ | Linux | libsecret / fallback → AES-128-CBC |
58
+ | Windows | DPAPI → AES-256-GCM (requires `win-dpapi`) |
59
+
60
+ ## Security
61
+
62
+ - Cookies are only sent to your authenticated tenant
63
+ - Transport uses HTTPS
64
+ - Local auth token stored with 0600 permissions at `~/.config/browser-sync/auth.json`
65
+ - No cookies are stored server-side — they're injected directly into the browser process
66
+
67
+ ## Programmatic API
68
+
69
+ ```typescript
70
+ import { extractStorageState, pushCookies, login } from "@vibetechnologies/browser-sync";
71
+
72
+ // Extract Google cookies from local Chrome
73
+ const state = await extractStorageState([".google.com", ".gmail.com"]);
74
+
75
+ // Push to cloud
76
+ await login("https://console.openclaw.vibebrowser.app", "your-token");
77
+ await pushCookies(state);
78
+ ```
package/dist/api.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * API client for syncing cookies to OpenClaw tenant cloud browser.
3
+ *
4
+ * Flow:
5
+ * 1. CLI starts localhost callback server, opens browser to /auth/cli
6
+ * 2. User authenticates on the web (Telegram OAuth or session)
7
+ * 3. Server redirects to localhost callback with token + username
8
+ * 4. CLI saves credentials, user runs `chrome-sync push`
9
+ */
10
+ import type { StorageState } from "./extract.js";
11
+ interface AuthConfig {
12
+ apiUrl: string;
13
+ token: string;
14
+ username: string;
15
+ subdomain: string;
16
+ }
17
+ /** Store auth credentials */
18
+ export declare function saveAuth(config: AuthConfig): void;
19
+ /** Load saved auth credentials */
20
+ export declare function loadAuth(): AuthConfig | null;
21
+ /** Clear saved auth */
22
+ export declare function clearAuth(): void;
23
+ /**
24
+ * Login via browser OAuth callback flow.
25
+ *
26
+ * 1. Starts a localhost HTTP server on a random port
27
+ * 2. Opens browser to apiUrl/auth/cli?callback_port=<port>
28
+ * 3. User authenticates on the web
29
+ * 4. Server redirects to http://localhost:<port>/callback?token=...&username=...&subdomain=...
30
+ * 5. CLI saves credentials and closes
31
+ */
32
+ export declare function loginViaBrowser(apiUrl?: string): Promise<AuthConfig>;
33
+ /**
34
+ * Login with a direct token (for CI/automation).
35
+ */
36
+ export declare function loginWithToken(apiUrl: string, token: string): Promise<AuthConfig>;
37
+ /**
38
+ * Push cookies to the tenant's cloud browser.
39
+ */
40
+ export declare function pushCookies(storageState: StorageState, options?: {
41
+ subdomain?: string;
42
+ }): Promise<{
43
+ injected: number;
44
+ errors: string[];
45
+ }>;
46
+ export {};
package/dist/api.js ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * API client for syncing cookies to OpenClaw tenant cloud browser.
3
+ *
4
+ * Flow:
5
+ * 1. CLI starts localhost callback server, opens browser to /auth/cli
6
+ * 2. User authenticates on the web (Telegram OAuth or session)
7
+ * 3. Server redirects to localhost callback with token + username
8
+ * 4. CLI saves credentials, user runs `chrome-sync push`
9
+ */
10
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
11
+ import { createServer } from "node:http";
12
+ import { homedir } from "node:os";
13
+ import { join } from "node:path";
14
+ const CONFIG_DIR = join(homedir(), ".config", "chrome-sync");
15
+ const TOKEN_FILE = join(CONFIG_DIR, "auth.json");
16
+ /** Store auth credentials */
17
+ export function saveAuth(config) {
18
+ mkdirSync(CONFIG_DIR, { recursive: true });
19
+ writeFileSync(TOKEN_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
20
+ }
21
+ /** Load saved auth credentials */
22
+ export function loadAuth() {
23
+ if (!existsSync(TOKEN_FILE))
24
+ return null;
25
+ try {
26
+ return JSON.parse(readFileSync(TOKEN_FILE, "utf-8"));
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ /** Clear saved auth */
33
+ export function clearAuth() {
34
+ if (existsSync(TOKEN_FILE)) {
35
+ writeFileSync(TOKEN_FILE, "", { mode: 0o600 });
36
+ }
37
+ }
38
+ /**
39
+ * Login via browser OAuth callback flow.
40
+ *
41
+ * 1. Starts a localhost HTTP server on a random port
42
+ * 2. Opens browser to apiUrl/auth/cli?callback_port=<port>
43
+ * 3. User authenticates on the web
44
+ * 4. Server redirects to http://localhost:<port>/callback?token=...&username=...&subdomain=...
45
+ * 5. CLI saves credentials and closes
46
+ */
47
+ export async function loginViaBrowser(apiUrl = "https://console.openclaw.vibebrowser.app") {
48
+ return new Promise((resolve, reject) => {
49
+ const server = createServer((req, res) => {
50
+ const url = new URL(req.url ?? "/", `http://localhost`);
51
+ if (url.pathname === "/callback") {
52
+ const token = url.searchParams.get("token");
53
+ const username = url.searchParams.get("username");
54
+ const subdomain = url.searchParams.get("subdomain");
55
+ if (!token) {
56
+ res.writeHead(400, { "Content-Type": "text/html" });
57
+ res.end("<html><body><h2>Authentication failed</h2><p>No token received. Close this window and try again.</p></body></html>");
58
+ server.close();
59
+ reject(new Error("No token received from server"));
60
+ return;
61
+ }
62
+ const config = {
63
+ apiUrl,
64
+ token,
65
+ username: username || "user",
66
+ subdomain: subdomain || "",
67
+ };
68
+ saveAuth(config);
69
+ res.writeHead(200, { "Content-Type": "text/html" });
70
+ res.end(`<html><body><h2>✓ Authenticated as ${config.username}</h2><p>You can close this window and return to the terminal.</p></body></html>`);
71
+ server.close();
72
+ resolve(config);
73
+ }
74
+ else {
75
+ res.writeHead(404);
76
+ res.end();
77
+ }
78
+ });
79
+ server.listen(0, "127.0.0.1", () => {
80
+ const addr = server.address();
81
+ if (!addr || typeof addr === "string") {
82
+ server.close();
83
+ reject(new Error("Failed to start callback server"));
84
+ return;
85
+ }
86
+ const port = addr.port;
87
+ const authUrl = `${apiUrl}/auth/cli?callback_port=${port}`;
88
+ // Open browser
89
+ import("node:child_process").then(({ exec }) => {
90
+ const openCmd = process.platform === "darwin"
91
+ ? `open "${authUrl}"`
92
+ : process.platform === "win32"
93
+ ? `start "" "${authUrl}"`
94
+ : `xdg-open "${authUrl}"`;
95
+ exec(openCmd);
96
+ });
97
+ console.log(` Opening browser for authentication...`);
98
+ console.log(` If it doesn't open, visit: ${authUrl}`);
99
+ });
100
+ // Timeout after 2 minutes
101
+ setTimeout(() => {
102
+ server.close();
103
+ reject(new Error("Authentication timed out (2 minutes). Try again."));
104
+ }, 120_000);
105
+ });
106
+ }
107
+ /**
108
+ * Login with a direct token (for CI/automation).
109
+ */
110
+ export async function loginWithToken(apiUrl, token) {
111
+ const res = await fetch(`${apiUrl}/admin/api/users`, {
112
+ headers: { Authorization: `Bearer ${token}` },
113
+ });
114
+ if (!res.ok) {
115
+ throw new Error(`Authentication failed: ${res.status} ${res.statusText}`);
116
+ }
117
+ const config = {
118
+ apiUrl,
119
+ token,
120
+ username: "admin",
121
+ subdomain: "",
122
+ };
123
+ saveAuth(config);
124
+ return config;
125
+ }
126
+ /**
127
+ * Push cookies to the tenant's cloud browser.
128
+ */
129
+ export async function pushCookies(storageState, options) {
130
+ const auth = loadAuth();
131
+ if (!auth) {
132
+ throw new Error("Not authenticated. Run `chrome-sync login` first.");
133
+ }
134
+ const subdomain = options?.subdomain || auth.subdomain;
135
+ const res = await fetch(`${auth.apiUrl}/admin/api/browser-sync/cookies`, {
136
+ method: "POST",
137
+ headers: {
138
+ Authorization: `Bearer ${auth.token}`,
139
+ "Content-Type": "application/json",
140
+ },
141
+ body: JSON.stringify({
142
+ storageState,
143
+ subdomain: subdomain || undefined,
144
+ }),
145
+ });
146
+ if (!res.ok) {
147
+ const body = await res.text();
148
+ throw new Error(`Failed to push cookies: ${res.status} — ${body}`);
149
+ }
150
+ return res.json();
151
+ }
152
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @vibetechnologies/chrome-sync CLI
4
+ *
5
+ * Sync browser cookies from local Chrome to OpenClaw cloud browser.
6
+ *
7
+ * Usage:
8
+ * chrome-sync login
9
+ * chrome-sync login --token <ADMIN_SECRET>
10
+ * chrome-sync push --domains google.com,github.com
11
+ * chrome-sync push --profile "Profile 1"
12
+ * chrome-sync profiles
13
+ * chrome-sync logout
14
+ */
15
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @vibetechnologies/chrome-sync CLI
4
+ *
5
+ * Sync browser cookies from local Chrome to OpenClaw cloud browser.
6
+ *
7
+ * Usage:
8
+ * chrome-sync login
9
+ * chrome-sync login --token <ADMIN_SECRET>
10
+ * chrome-sync push --domains google.com,github.com
11
+ * chrome-sync push --profile "Profile 1"
12
+ * chrome-sync profiles
13
+ * chrome-sync logout
14
+ */
15
+ import { Command } from "commander";
16
+ import { extractStorageState } from "./extract.js";
17
+ import { loginViaBrowser, loginWithToken, pushCookies, loadAuth, clearAuth } from "./api.js";
18
+ const program = new Command();
19
+ program
20
+ .name("chrome-sync")
21
+ .description("Sync browser cookies and sessions from local Chrome to OpenClaw cloud browser")
22
+ .version("0.4.0");
23
+ program
24
+ .command("login")
25
+ .description("Authenticate with OpenClaw (opens browser)")
26
+ .option("--token <token>", "Use a direct API token instead of browser auth")
27
+ .option("--api-url <url>", "OpenClaw API URL", "https://console.openclaw.vibebrowser.app")
28
+ .action(async (opts) => {
29
+ try {
30
+ let config;
31
+ if (opts.token) {
32
+ config = await loginWithToken(opts.apiUrl, opts.token);
33
+ }
34
+ else {
35
+ config = await loginViaBrowser(opts.apiUrl);
36
+ }
37
+ console.log(`✓ Authenticated as ${config.username}`);
38
+ if (config.subdomain) {
39
+ console.log(` Tenant: ${config.subdomain}`);
40
+ }
41
+ console.log(` API: ${config.apiUrl}`);
42
+ }
43
+ catch (err) {
44
+ console.error(`✗ Login failed: ${err.message}`);
45
+ process.exit(1);
46
+ }
47
+ });
48
+ program
49
+ .command("push")
50
+ .description("Extract and push cookies to cloud browser")
51
+ .option("--domains <domains>", "Comma-separated domains to sync (omit for all cookies)")
52
+ .option("--profile <profile>", "Chrome profile name", "Default")
53
+ .option("--subdomain <subdomain>", "Target tenant subdomain")
54
+ .option("--dry-run", "Extract cookies but don't push", false)
55
+ .action(async (opts) => {
56
+ try {
57
+ // Check auth first
58
+ let auth = loadAuth();
59
+ if (!auth) {
60
+ console.log("Not authenticated. Starting login...\n");
61
+ auth = await loginViaBrowser();
62
+ console.log(`✓ Authenticated as ${auth.username}\n`);
63
+ }
64
+ const domains = opts.domains
65
+ ? opts.domains
66
+ .split(",")
67
+ .map((d) => d.trim())
68
+ .map((d) => (d.startsWith(".") ? d : `.${d}`))
69
+ : [];
70
+ const label = domains.length > 0 ? domains.join(", ") : "ALL";
71
+ console.log(`Extracting cookies for: ${label} (profile: ${opts.profile})`);
72
+ const storageState = await extractStorageState(domains, opts.profile);
73
+ console.log(` Found ${storageState.cookies.length} cookies`);
74
+ if (storageState.cookies.length === 0) {
75
+ console.log(" No cookies found. Make sure you're logged into these sites in Chrome.");
76
+ process.exit(1);
77
+ }
78
+ if (opts.dryRun) {
79
+ console.log("\n Dry run — cookies extracted but not pushed.");
80
+ console.log(" Domains covered:");
81
+ const domainSet = new Set(storageState.cookies.map((c) => c.domain));
82
+ for (const d of domainSet) {
83
+ const count = storageState.cookies.filter((c) => c.domain === d).length;
84
+ console.log(` ${d}: ${count} cookies`);
85
+ }
86
+ return;
87
+ }
88
+ console.log(" Pushing to cloud browser...");
89
+ const result = await pushCookies(storageState, {
90
+ subdomain: opts.subdomain,
91
+ });
92
+ console.log(`✓ Injected ${result.injected} cookies into cloud browser`);
93
+ if (result.errors.length > 0) {
94
+ console.warn(` Warnings: ${result.errors.join(", ")}`);
95
+ }
96
+ }
97
+ catch (err) {
98
+ console.error(`✗ Failed: ${err.message}`);
99
+ process.exit(1);
100
+ }
101
+ });
102
+ program
103
+ .command("profiles")
104
+ .description("List available Chrome profiles")
105
+ .action(() => {
106
+ const { getChromeProfileDir } = require("./extract.js");
107
+ const { readdirSync } = require("node:fs");
108
+ const { dirname } = require("node:path");
109
+ const { existsSync } = require("node:fs");
110
+ const defaultDir = getChromeProfileDir("Default");
111
+ const chromeDir = dirname(defaultDir);
112
+ if (!existsSync(chromeDir)) {
113
+ console.log("Chrome profile directory not found.");
114
+ return;
115
+ }
116
+ const profiles = readdirSync(chromeDir, { withFileTypes: true })
117
+ .filter((d) => d.isDirectory() &&
118
+ (d.name === "Default" || d.name.startsWith("Profile ")))
119
+ .map((d) => d.name);
120
+ console.log("Available Chrome profiles:");
121
+ for (const p of profiles) {
122
+ console.log(` ${p}`);
123
+ }
124
+ });
125
+ program
126
+ .command("logout")
127
+ .description("Clear saved authentication")
128
+ .action(() => {
129
+ clearAuth();
130
+ console.log("✓ Logged out");
131
+ });
132
+ program.parse();
133
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE7F,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CACV,+EAA+E,CAChF;KACA,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,4CAA4C,CAAC;KACzD,MAAM,CAAC,iBAAiB,EAAE,gDAAgD,CAAC;KAC3E,MAAM,CACL,iBAAiB,EACjB,kBAAkB,EAClB,0CAA0C,CAC3C;KACA,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,CAAC;QACH,IAAI,MAAM,CAAC;QACX,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,mBAAmB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,2CAA2C,CAAC;KACxD,MAAM,CACL,qBAAqB,EACrB,wDAAwD,CACzD;KACA,MAAM,CAAC,qBAAqB,EAAE,qBAAqB,EAAE,SAAS,CAAC;KAC/D,MAAM,CAAC,yBAAyB,EAAE,yBAAyB,CAAC;KAC5D,MAAM,CAAC,WAAW,EAAE,gCAAgC,EAAE,KAAK,CAAC;KAC5D,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,CAAC;QACH,mBAAmB;QACnB,IAAI,IAAI,GAAG,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;YACtD,IAAI,GAAG,MAAM,eAAe,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO;YAC1B,CAAC,CAAC,IAAI,CAAC,OAAO;iBACT,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBAC5B,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC1D,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC9D,OAAO,CAAC,GAAG,CACT,2BAA2B,KAAK,cAAc,IAAI,CAAC,OAAO,GAAG,CAC9D,CAAC;QAEF,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,WAAW,YAAY,CAAC,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;QAE9D,IAAI,YAAY,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;YACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;YAC/D,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAClC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YACrE,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC1B,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;gBACxE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC;YAC5C,CAAC;YACD,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,YAAY,EAAE;YAC7C,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,QAAQ,6BAA6B,CAAC,CAAC;QACxE,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,gCAAgC,CAAC;KAC7C,MAAM,CAAC,GAAG,EAAE;IACX,MAAM,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,cAAc,CAAkC,CAAC;IACzF,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAE1C,MAAM,UAAU,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAEtC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QACnD,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SAC7D,MAAM,CACL,CAAC,CAAM,EAAE,EAAE,CACT,CAAC,CAAC,WAAW,EAAE;QACf,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAC1D;SACA,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE3B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,4BAA4B,CAAC;KACzC,MAAM,CAAC,GAAG,EAAE;IACX,SAAS,EAAE,CAAC;IACZ,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Chrome cookie extraction — reads and decrypts cookies from local Chrome profile.
3
+ *
4
+ * Supports: macOS (Keychain), Linux (libsecret / fallback "peanuts"), Windows (DPAPI via AES-GCM).
5
+ */
6
+ export interface Cookie {
7
+ name: string;
8
+ value: string;
9
+ domain: string;
10
+ path: string;
11
+ expires: number;
12
+ httpOnly: boolean;
13
+ secure: boolean;
14
+ sameSite: "Strict" | "Lax" | "None";
15
+ }
16
+ export interface StorageState {
17
+ cookies: Cookie[];
18
+ origins: {
19
+ origin: string;
20
+ localStorage: {
21
+ name: string;
22
+ value: string;
23
+ }[];
24
+ }[];
25
+ }
26
+ /** Get Chrome profile directory for current OS */
27
+ export declare function getChromeProfileDir(profile?: string): string;
28
+ /** Get Chrome cookie DB path */
29
+ export declare function getCookieDbPath(profile?: string): string;
30
+ /**
31
+ * Extract cookies from local Chrome for specific domains (or all cookies if domains is empty).
32
+ *
33
+ * @param domains - Array of domains to extract (e.g., [".google.com"]). Empty = all cookies.
34
+ * @param profile - Chrome profile name (default: "Default")
35
+ */
36
+ export declare function extractCookies(domains: string[], profile?: string): Promise<Cookie[]>;
37
+ /**
38
+ * Extract cookies and format as Playwright-compatible StorageState
39
+ */
40
+ export declare function extractStorageState(domains: string[], profile?: string): Promise<StorageState>;