pi-browser-use 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +39 -11
  2. package/dist/auth-verifiers.d.ts +60 -0
  3. package/dist/auth-verifiers.d.ts.map +1 -0
  4. package/dist/auth-verifiers.js +92 -0
  5. package/dist/auth-verifiers.js.map +1 -0
  6. package/dist/chrome-launcher.d.ts +100 -0
  7. package/dist/chrome-launcher.d.ts.map +1 -0
  8. package/dist/chrome-launcher.js +268 -0
  9. package/dist/chrome-launcher.js.map +1 -0
  10. package/dist/config.d.ts +3 -1
  11. package/dist/config.d.ts.map +1 -1
  12. package/dist/config.js +28 -5
  13. package/dist/config.js.map +1 -1
  14. package/dist/doctor.d.ts +8 -1
  15. package/dist/doctor.d.ts.map +1 -1
  16. package/dist/doctor.js +16 -6
  17. package/dist/doctor.js.map +1 -1
  18. package/dist/existing-flow.d.ts +68 -0
  19. package/dist/existing-flow.d.ts.map +1 -0
  20. package/dist/existing-flow.js +128 -0
  21. package/dist/existing-flow.js.map +1 -0
  22. package/dist/focus-policy.d.ts +28 -0
  23. package/dist/focus-policy.d.ts.map +1 -0
  24. package/dist/focus-policy.js +28 -0
  25. package/dist/focus-policy.js.map +1 -0
  26. package/dist/index.d.ts +2 -2
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +494 -39
  29. package/dist/index.js.map +1 -1
  30. package/dist/named-profile.d.ts +47 -0
  31. package/dist/named-profile.d.ts.map +1 -0
  32. package/dist/named-profile.js +123 -0
  33. package/dist/named-profile.js.map +1 -0
  34. package/dist/persistent-backend.d.ts +77 -0
  35. package/dist/persistent-backend.d.ts.map +1 -0
  36. package/dist/persistent-backend.js +166 -0
  37. package/dist/persistent-backend.js.map +1 -0
  38. package/dist/persistent-store.d.ts +35 -0
  39. package/dist/persistent-store.d.ts.map +1 -0
  40. package/dist/persistent-store.js +98 -0
  41. package/dist/persistent-store.js.map +1 -0
  42. package/dist/profile-lock.d.ts +40 -0
  43. package/dist/profile-lock.d.ts.map +1 -0
  44. package/dist/profile-lock.js +165 -0
  45. package/dist/profile-lock.js.map +1 -0
  46. package/dist/profile.d.ts +3 -1
  47. package/dist/profile.d.ts.map +1 -1
  48. package/dist/profile.js +15 -6
  49. package/dist/profile.js.map +1 -1
  50. package/dist/session-manager.d.ts +125 -0
  51. package/dist/session-manager.d.ts.map +1 -0
  52. package/dist/session-manager.js +275 -0
  53. package/dist/session-manager.js.map +1 -0
  54. package/dist/session.d.ts +92 -0
  55. package/dist/session.d.ts.map +1 -0
  56. package/dist/session.js +29 -0
  57. package/dist/session.js.map +1 -0
  58. package/dist/setup-flow.d.ts +78 -0
  59. package/dist/setup-flow.d.ts.map +1 -0
  60. package/dist/setup-flow.js +97 -0
  61. package/dist/setup-flow.js.map +1 -0
  62. package/dist/tab-bridge.d.ts +71 -0
  63. package/dist/tab-bridge.d.ts.map +1 -0
  64. package/dist/tab-bridge.js +198 -0
  65. package/dist/tab-bridge.js.map +1 -0
  66. package/extension/README.md +33 -0
  67. package/extension/background.js +185 -0
  68. package/extension/manifest.json +12 -0
  69. package/package.json +2 -1
  70. package/skills/auth-bootstrap/SKILL.md +13 -0
  71. package/skills/browser-policy/SKILL.md +29 -4
  72. package/skills/gmail-auth/SKILL.md +51 -0
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Durable Persistent-mode metadata (spec section 2).
3
+ *
4
+ * Only durable state is persisted: initialization flag, profile path, last
5
+ * working launch mode, and last bootstrap timestamp. Passwords, cookies,
6
+ * tokens, or copied browser credentials must never be stored here — Chrome
7
+ * owns those inside its profile directory.
8
+ *
9
+ * Default location is a sibling of the profile directory:
10
+ * `<profileDir>.meta.json` (e.g. `~/.pi/browser-profile.meta.json`), so a
11
+ * profile move/rename never orphans its metadata.
12
+ */
13
+ import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
14
+ import { dirname } from 'node:path';
15
+ import { DEFAULT_PROFILE_DIR } from './config.js';
16
+ export function metadataPathFor(profileDir = DEFAULT_PROFILE_DIR) {
17
+ return `${profileDir}.meta.json`;
18
+ }
19
+ export function defaultMetadata(profileDir = DEFAULT_PROFILE_DIR) {
20
+ return { initialized: false, profilePath: profileDir };
21
+ }
22
+ /** Load metadata; returns uninitialized defaults when absent or corrupt. */
23
+ export function loadPersistentMetadata(profileDir = DEFAULT_PROFILE_DIR) {
24
+ const path = metadataPathFor(profileDir);
25
+ try {
26
+ const raw = JSON.parse(readFileSync(path, 'utf8'));
27
+ return {
28
+ initialized: raw.initialized === true,
29
+ profilePath: typeof raw.profilePath === 'string' ? raw.profilePath : profileDir,
30
+ lastSuccessfulMode: raw.lastSuccessfulMode === 'headless' || raw.lastSuccessfulMode === 'headed'
31
+ ? raw.lastSuccessfulMode
32
+ : undefined,
33
+ lastBootstrapAt: typeof raw.lastBootstrapAt === 'string' ? raw.lastBootstrapAt : undefined,
34
+ };
35
+ }
36
+ catch {
37
+ return defaultMetadata(profileDir);
38
+ }
39
+ }
40
+ /** Atomically persist metadata (write-then-rename via temp file). */
41
+ export function savePersistentMetadata(meta) {
42
+ const path = metadataPathFor(meta.profilePath);
43
+ mkdirSync(dirname(path), { recursive: true });
44
+ writeFileSync(path, `${JSON.stringify(meta, null, 2)}\n`, 'utf8');
45
+ }
46
+ /** Record a completed bootstrap: initialized now, timestamped. */
47
+ export function markBootstrapped(profileDir = DEFAULT_PROFILE_DIR, at = new Date().toISOString()) {
48
+ const meta = {
49
+ ...loadPersistentMetadata(profileDir),
50
+ initialized: true,
51
+ profilePath: profileDir,
52
+ lastBootstrapAt: at,
53
+ };
54
+ savePersistentMetadata(meta);
55
+ return meta;
56
+ }
57
+ /** Record which launch mode last automated successfully. */
58
+ export function markAutomationResult(profileDir, mode) {
59
+ const meta = {
60
+ ...loadPersistentMetadata(profileDir),
61
+ profilePath: profileDir,
62
+ lastSuccessfulMode: mode,
63
+ };
64
+ savePersistentMetadata(meta);
65
+ return meta;
66
+ }
67
+ /**
68
+ * Per-origin headed-background preferences (spec section 8). Stored beside
69
+ * the metadata file (`<profileDir>.sites.json`); origins only, never
70
+ * credentials. A site pinned here starts headed-background instead of
71
+ * globally downgrading Persistent because one site rejects headless.
72
+ */
73
+ export function sitePreferencesPathFor(profileDir = DEFAULT_PROFILE_DIR) {
74
+ return `${profileDir}.sites.json`;
75
+ }
76
+ /** Load per-origin preferences; empty when absent or corrupt. */
77
+ export function loadSitePreferences(profileDir = DEFAULT_PROFILE_DIR) {
78
+ try {
79
+ const raw = JSON.parse(readFileSync(sitePreferencesPathFor(profileDir), 'utf8'));
80
+ if (!Array.isArray(raw))
81
+ return [];
82
+ return raw.filter((entry) => typeof entry === 'object' &&
83
+ entry !== null &&
84
+ typeof entry.origin === 'string' &&
85
+ (entry.executionMode === 'headless' ||
86
+ entry.executionMode === 'headed-background'));
87
+ }
88
+ catch {
89
+ return [];
90
+ }
91
+ }
92
+ /** Persist per-origin preferences. */
93
+ export function saveSitePreferences(profileDir, preferences) {
94
+ const path = sitePreferencesPathFor(profileDir);
95
+ mkdirSync(dirname(path), { recursive: true });
96
+ writeFileSync(path, `${JSON.stringify(preferences, null, 2)}\n`, 'utf8');
97
+ }
98
+ //# sourceMappingURL=persistent-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistent-store.js","sourceRoot":"","sources":["../src/persistent-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,MAAM,UAAU,eAAe,CAAC,aAAqB,mBAAmB;IACtE,OAAO,GAAG,UAAU,YAAY,CAAA;AAClC,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,aAAqB,mBAAmB;IAExC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,CAAA;AACxD,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,sBAAsB,CACpC,aAAqB,mBAAmB;IAExC,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAuC,CAAA;QACxF,OAAO;YACL,WAAW,EAAE,GAAG,CAAC,WAAW,KAAK,IAAI;YACrC,WAAW,EAAE,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU;YAC/E,kBAAkB,EAChB,GAAG,CAAC,kBAAkB,KAAK,UAAU,IAAI,GAAG,CAAC,kBAAkB,KAAK,QAAQ;gBAC1E,CAAC,CAAC,GAAG,CAAC,kBAAkB;gBACxB,CAAC,CAAC,SAAS;YACf,eAAe,EAAE,OAAO,GAAG,CAAC,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;SAC3F,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,eAAe,CAAC,UAAU,CAAC,CAAA;IACpC,CAAC;AACH,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,sBAAsB,CAAC,IAA+B;IACpE,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAC9C,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7C,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AACnE,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,gBAAgB,CAC9B,aAAqB,mBAAmB,EACxC,KAAa,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;IAErC,MAAM,IAAI,GAA8B;QACtC,GAAG,sBAAsB,CAAC,UAAU,CAAC;QACrC,WAAW,EAAE,IAAI;QACjB,WAAW,EAAE,UAAU;QACvB,eAAe,EAAE,EAAE;KACpB,CAAA;IACD,sBAAsB,CAAC,IAAI,CAAC,CAAA;IAC5B,OAAO,IAAI,CAAA;AACb,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,oBAAoB,CAClC,UAAkB,EAClB,IAA2B;IAE3B,MAAM,IAAI,GAA8B;QACtC,GAAG,sBAAsB,CAAC,UAAU,CAAC;QACrC,WAAW,EAAE,UAAU;QACvB,kBAAkB,EAAE,IAAI;KACzB,CAAA;IACD,sBAAsB,CAAC,IAAI,CAAC,CAAA;IAC5B,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,aAAqB,mBAAmB;IAC7E,OAAO,GAAG,UAAU,aAAa,CAAA;AACnC,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,mBAAmB,CACjC,aAAqB,mBAAmB;IAExC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,sBAAsB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAY,CAAA;QAC3F,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,CAAA;QAClC,OAAO,GAAG,CAAC,MAAM,CACf,CAAC,KAAK,EAAkC,EAAE,CACxC,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,OAAQ,KAA+B,CAAC,MAAM,KAAK,QAAQ;YAC3D,CAAE,KAA+B,CAAC,aAAa,KAAK,UAAU;gBAC3D,KAA+B,CAAC,aAAa,KAAK,mBAAmB,CAAC,CAC5E,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,mBAAmB,CACjC,UAAkB,EAClB,WAAoC;IAEpC,MAAM,IAAI,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAA;IAC/C,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7C,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAC1E,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Single-process guard for a Chrome user-data directory (spec section 4).
3
+ *
4
+ * Chrome corrupts state when two processes share one user-data-dir, so every
5
+ * Pi-owned launch/shutdown path must hold this lock:
6
+ *
7
+ * ```text
8
+ * one Chrome process <-> one persistent profile
9
+ * ```
10
+ *
11
+ * Implemented as a sibling `<profileDir>.lock` file holding `{ pid,
12
+ * createdAt }`. Stale locks (dead pid or age beyond `staleMs`) are reclaimed;
13
+ * live locks throw {@link ProfileLockedError}.
14
+ */
15
+ export declare class ProfileLockedError extends Error {
16
+ readonly profileDir: string;
17
+ readonly holderPid?: number;
18
+ constructor(profileDir: string, holderPid?: number);
19
+ }
20
+ export interface ProfileLockHandle {
21
+ readonly profileDir: string;
22
+ readonly lockPath: string;
23
+ released: boolean;
24
+ release(): void;
25
+ }
26
+ export declare function lockPathFor(profileDir: string): string;
27
+ export interface AcquireLockOptions {
28
+ /** Locks older than this with a dead holder are reclaimed. Default 5 min. */
29
+ staleMs?: number;
30
+ }
31
+ /**
32
+ * Acquire the exclusive lock for `profileDir`. Throws ProfileLockedError when
33
+ * a live Chrome (or another Pi process) holds it.
34
+ */
35
+ export declare function acquireProfileLock(profileDir: string, options?: AcquireLockOptions): ProfileLockHandle;
36
+ /** True when a live holder currently owns the profile lock. */
37
+ export declare function isProfileLocked(profileDir: string): boolean;
38
+ /** Run `fn` while holding the profile lock, always releasing afterwards. */
39
+ export declare function withProfileLock<T>(profileDir: string, fn: (lock: ProfileLockHandle) => Promise<T>, options?: AcquireLockOptions): Promise<T>;
40
+ //# sourceMappingURL=profile-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-lock.d.ts","sourceRoot":"","sources":["../src/profile-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;gBAEf,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAUnD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtD;AAmDD,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,iBAAiB,CAgCnB;AAoBD,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAc3D;AAED,4EAA4E;AAC5E,wBAAsB,eAAe,CAAC,CAAC,EACrC,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC,EAC3C,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,CAAC,CAAC,CAOZ"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Single-process guard for a Chrome user-data directory (spec section 4).
3
+ *
4
+ * Chrome corrupts state when two processes share one user-data-dir, so every
5
+ * Pi-owned launch/shutdown path must hold this lock:
6
+ *
7
+ * ```text
8
+ * one Chrome process <-> one persistent profile
9
+ * ```
10
+ *
11
+ * Implemented as a sibling `<profileDir>.lock` file holding `{ pid,
12
+ * createdAt }`. Stale locks (dead pid or age beyond `staleMs`) are reclaimed;
13
+ * live locks throw {@link ProfileLockedError}.
14
+ */
15
+ import { closeSync, mkdirSync, openSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
16
+ import { dirname } from 'node:path';
17
+ export class ProfileLockedError extends Error {
18
+ profileDir;
19
+ holderPid;
20
+ constructor(profileDir, holderPid) {
21
+ super(holderPid !== undefined
22
+ ? `Chrome profile is already in use by pid ${holderPid}: ${profileDir}`
23
+ : `Chrome profile is already in use: ${profileDir}`);
24
+ this.name = 'ProfileLockedError';
25
+ this.profileDir = profileDir;
26
+ this.holderPid = holderPid;
27
+ }
28
+ }
29
+ export function lockPathFor(profileDir) {
30
+ return `${profileDir}.lock`;
31
+ }
32
+ function readLockPid(lockPath) {
33
+ try {
34
+ const raw = JSON.parse(readFileSync(lockPath, 'utf8'));
35
+ return typeof raw.pid === 'number' && Number.isInteger(raw.pid) ? raw.pid : undefined;
36
+ }
37
+ catch {
38
+ return undefined;
39
+ }
40
+ }
41
+ function readLockAgeMs(lockPath) {
42
+ try {
43
+ const raw = JSON.parse(readFileSync(lockPath, 'utf8'));
44
+ if (typeof raw.createdAt !== 'string')
45
+ return undefined;
46
+ const age = Date.now() - Date.parse(raw.createdAt);
47
+ return Number.isFinite(age) ? age : undefined;
48
+ }
49
+ catch {
50
+ return undefined;
51
+ }
52
+ }
53
+ function isPidAlive(pid) {
54
+ try {
55
+ process.kill(pid, 0);
56
+ return true;
57
+ }
58
+ catch {
59
+ return false;
60
+ }
61
+ }
62
+ function tryCreateLockFile(lockPath) {
63
+ let fd;
64
+ try {
65
+ fd = openSync(lockPath, 'wx');
66
+ writeFileSync(fd, JSON.stringify({ pid: process.pid, createdAt: new Date().toISOString() }));
67
+ return true;
68
+ }
69
+ catch (error) {
70
+ if (error.code === 'EEXIST')
71
+ return false;
72
+ throw error;
73
+ }
74
+ finally {
75
+ if (fd !== undefined) {
76
+ try {
77
+ closeSync(fd);
78
+ }
79
+ catch {
80
+ // Best effort; the lock content is already written.
81
+ }
82
+ }
83
+ }
84
+ }
85
+ /**
86
+ * Acquire the exclusive lock for `profileDir`. Throws ProfileLockedError when
87
+ * a live Chrome (or another Pi process) holds it.
88
+ */
89
+ export function acquireProfileLock(profileDir, options) {
90
+ const staleMs = options?.staleMs ?? 5 * 60 * 1000;
91
+ const lockPath = lockPathFor(profileDir);
92
+ // Ensure the parent exists so the sibling lock file can be created.
93
+ try {
94
+ mkdirSync(dirname(lockPath), { recursive: true });
95
+ }
96
+ catch {
97
+ // Parent creation failure surfaces on lock creation below.
98
+ }
99
+ if (tryCreateLockFile(lockPath)) {
100
+ return makeHandle(profileDir, lockPath);
101
+ }
102
+ const holderPid = readLockPid(lockPath);
103
+ const ageMs = readLockAgeMs(lockPath);
104
+ const holderAlive = holderPid !== undefined && isPidAlive(holderPid);
105
+ const isStale = !holderAlive || (ageMs !== undefined && ageMs > staleMs);
106
+ if (isStale) {
107
+ try {
108
+ rmSync(lockPath, { force: true });
109
+ }
110
+ catch {
111
+ // Fall through to the error below if removal failed.
112
+ }
113
+ if (tryCreateLockFile(lockPath)) {
114
+ return makeHandle(profileDir, lockPath);
115
+ }
116
+ }
117
+ throw new ProfileLockedError(profileDir, holderPid);
118
+ }
119
+ function makeHandle(profileDir, lockPath) {
120
+ const handle = {
121
+ profileDir,
122
+ lockPath,
123
+ released: false,
124
+ release() {
125
+ if (handle.released)
126
+ return;
127
+ handle.released = true;
128
+ try {
129
+ rmSync(lockPath, { force: true });
130
+ }
131
+ catch {
132
+ // Lock files are best-effort on shutdown.
133
+ }
134
+ },
135
+ };
136
+ return handle;
137
+ }
138
+ /** True when a live holder currently owns the profile lock. */
139
+ export function isProfileLocked(profileDir) {
140
+ const lockPath = lockPathFor(profileDir);
141
+ const holderPid = readLockPid(lockPath);
142
+ if (holderPid === undefined) {
143
+ // Unparseable/missing lock file: treat a present file as locked to stay
144
+ // safe, absent as unlocked.
145
+ try {
146
+ readFileSync(lockPath);
147
+ return true;
148
+ }
149
+ catch {
150
+ return false;
151
+ }
152
+ }
153
+ return isPidAlive(holderPid);
154
+ }
155
+ /** Run `fn` while holding the profile lock, always releasing afterwards. */
156
+ export async function withProfileLock(profileDir, fn, options) {
157
+ const lock = acquireProfileLock(profileDir, options);
158
+ try {
159
+ return await fn(lock);
160
+ }
161
+ finally {
162
+ lock.release();
163
+ }
164
+ }
165
+ //# sourceMappingURL=profile-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-lock.js","sourceRoot":"","sources":["../src/profile-lock.ts"],"names":[],"mappings":"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"}
package/dist/profile.d.ts CHANGED
@@ -5,7 +5,9 @@ import { type BrowserUseConfig } from './config.js';
5
5
  * moved aside so Chrome starts fresh instead of showing a "can't read your
6
6
  * preferences" dialog on every launch. An explicit custom userDataDir in the
7
7
  * same state fails fast with a remediation hint instead of silently
8
- * discarding the user's data.
8
+ * discarding the user's data. Persistent launches additionally pin the named
9
+ * `pi-browser-use` profile (one-time legacy migration, refuses while an
10
+ * external Chrome holds the root).
9
11
  */
10
12
  export declare function prepareBrowserProfile(config: BrowserUseConfig): void;
11
13
  //# sourceMappingURL=profile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAwBxE;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CA2BpE"}
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAyBxE;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CA+BpE"}
package/dist/profile.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { accessSync, constants, renameSync, statSync } from 'node:fs';
2
2
  import { dirname, join } from 'node:path';
3
3
  import { DEFAULT_PROFILE_DIR } from './config.js';
4
+ import { ensureNamedProfile } from './named-profile.js';
4
5
  function isRootOwned(path) {
5
6
  try {
6
7
  const stat = statSync(path);
@@ -30,20 +31,23 @@ function isUnusableDir(path) {
30
31
  * moved aside so Chrome starts fresh instead of showing a "can't read your
31
32
  * preferences" dialog on every launch. An explicit custom userDataDir in the
32
33
  * same state fails fast with a remediation hint instead of silently
33
- * discarding the user's data.
34
+ * discarding the user's data. Persistent launches additionally pin the named
35
+ * `pi-browser-use` profile (one-time legacy migration, refuses while an
36
+ * external Chrome holds the root).
34
37
  */
35
38
  export function prepareBrowserProfile(config) {
36
- if (config.browserUrl || config.wsEndpoint)
39
+ if (config.browserUrl || config.wsEndpoint || config.autoConnect)
37
40
  return;
38
41
  const dir = config.userDataDir ?? (config.sessionMode === 'persistent' ? DEFAULT_PROFILE_DIR : undefined);
39
- if (!dir || dir !== DEFAULT_PROFILE_DIR) {
40
- if (dir && isUnusableDir(dir)) {
42
+ if (!dir)
43
+ return;
44
+ if (dir !== DEFAULT_PROFILE_DIR) {
45
+ if (isUnusableDir(dir)) {
41
46
  throw new Error(`Browser profile at ${dir} is not accessible (likely root-owned from running under sudo). ` +
42
47
  `chown it back with: sudo chown -R $(id -un):$(id -gn) ${JSON.stringify(dir)}`);
43
48
  }
44
- return;
45
49
  }
46
- if (isUnusableDir(dir)) {
50
+ else if (isUnusableDir(dir)) {
47
51
  const aside = join(dirname(DEFAULT_PROFILE_DIR), `browser-profile.inaccessible-${Date.now()}`);
48
52
  console.error(`[pi-browser-use] default browser profile is inaccessible; moving it aside to ${aside} and starting fresh.`);
49
53
  try {
@@ -54,5 +58,10 @@ export function prepareBrowserProfile(config) {
54
58
  `Fix ownership with: sudo chown -R $(id -un):$(id -gn) ${JSON.stringify(dir)}`);
55
59
  }
56
60
  }
61
+ // Pin the named Pi profile for persistent launches (fresh migrations
62
+ // happen here, under no running Chrome by construction of the callers).
63
+ if (config.sessionMode === 'persistent') {
64
+ ensureNamedProfile(dir);
65
+ }
57
66
  }
58
67
  //# sourceMappingURL=profile.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,mBAAmB,EAAyB,MAAM,aAAa,CAAA;AAExE,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC3B,MAAM,MAAM,GAAI,OAAgD,CAAC,MAAM,CAAA;QACvE,OAAO,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,OAAO,MAAM,KAAK,UAAU,IAAI,MAAM,EAAE,KAAK,CAAC,CAAA;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,CAAC;QACH,IAAI,WAAW,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QAClC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;QACjD,OAAO,KAAK,CAAA;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uEAAuE;QACvE,8BAA8B;QAC9B,OAAQ,KAA+B,CAAC,IAAI,KAAK,QAAQ,CAAA;IAC3D,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAwB;IAC5D,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU;QAAE,OAAM;IAClD,MAAM,GAAG,GACP,MAAM,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC/F,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,mBAAmB,EAAE,CAAC;QACxC,IAAI,GAAG,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,sBAAsB,GAAG,kEAAkE;gBACzF,yDAAyD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CACjF,CAAA;QACH,CAAC;QACD,OAAM;IACR,CAAC;IACD,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,gCAAgC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QAC9F,OAAO,CAAC,KAAK,CACX,gFAAgF,KAAK,sBAAsB,CAC5G,CAAA;QACD,IAAI,CAAC;YACH,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,sBAAsB,GAAG,mDAAmD;gBAC1E,yDAAyD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CACjF,CAAA;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,mBAAmB,EAAyB,MAAM,aAAa,CAAA;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAEvD,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC3B,MAAM,MAAM,GAAI,OAAgD,CAAC,MAAM,CAAA;QACvE,OAAO,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,OAAO,MAAM,KAAK,UAAU,IAAI,MAAM,EAAE,KAAK,CAAC,CAAA;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,CAAC;QACH,IAAI,WAAW,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QAClC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;QACjD,OAAO,KAAK,CAAA;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uEAAuE;QACvE,8BAA8B;QAC9B,OAAQ,KAA+B,CAAC,IAAI,KAAK,QAAQ,CAAA;IAC3D,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAwB;IAC5D,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,WAAW;QAAE,OAAM;IACxE,MAAM,GAAG,GACP,MAAM,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC/F,IAAI,CAAC,GAAG;QAAE,OAAM;IAChB,IAAI,GAAG,KAAK,mBAAmB,EAAE,CAAC;QAChC,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,sBAAsB,GAAG,kEAAkE;gBACzF,yDAAyD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CACjF,CAAA;QACH,CAAC;IACH,CAAC;SAAM,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,gCAAgC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QAC9F,OAAO,CAAC,KAAK,CACX,gFAAgF,KAAK,sBAAsB,CAC5G,CAAA;QACD,IAAI,CAAC;YACH,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,sBAAsB,GAAG,mDAAmD;gBAC1E,yDAAyD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CACjF,CAAA;QACH,CAAC;IACH,CAAC;IACD,qEAAqE;IACrE,wEAAwE;IACxE,IAAI,MAAM,CAAC,WAAW,KAAK,YAAY,EAAE,CAAC;QACxC,kBAAkB,CAAC,GAAG,CAAC,CAAA;IACzB,CAAC;AACH,CAAC"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * BrowserSessionManager: mode-specific behavior behind one stable API
3
+ * (spec sections 1, 8, 21, 24, 25).
4
+ *
5
+ * ```text
6
+ * Pi Skills / Agent → BrowserSessionManager → Fresh | Persistent | Existing
7
+ * ```
8
+ *
9
+ * - Fresh: temporary profile, headless, deleted afterwards (spec 12).
10
+ * - Persistent: Pi-owned profile with headless-first automation and a
11
+ * headed-background fallback per origin (spec 2, 4, 7, 8, 24).
12
+ * - Existing: the user's own Chrome via autoConnect; Pi tabs are brokered by
13
+ * the Pi extension into the collapsed `pi-browser-use` group (spec 13-20).
14
+ *
15
+ * This module holds the state machines, capability resolution, and fallback
16
+ * hierarchies. Process launching (chrome-launcher), locking (profile-lock),
17
+ * and durable metadata (persistent-store) are injected collaborators so the
18
+ * logic stays unit-testable without a real Chrome.
19
+ */
20
+ import type { BrowserCapabilityRequest, BrowserSession, BrowserSessionMode, BrowserStatus, PageHandle, PersistentBrowserMetadata, PersistentExecutionMode, PersistentState, SiteBrowserPreference } from './session.js';
21
+ export type { BrowserSession, BrowserStatus, PageHandle } from './session.js';
22
+ /** Minimal transport SPI a session uses to drive pages (MCP/CDP/extension). */
23
+ export interface SessionTransport {
24
+ openPage(url: string): Promise<PageHandle>;
25
+ listPages(): Promise<PageHandle[]>;
26
+ closePage(page: PageHandle): Promise<void>;
27
+ requestVisibleBrowser?(reason: string): Promise<void>;
28
+ }
29
+ /** In-memory transport for tests and for wiring custom backends. */
30
+ export declare function createMemoryTransport(): SessionTransport & {
31
+ pages: PageHandle[];
32
+ };
33
+ declare abstract class BaseSession implements BrowserSession {
34
+ readonly mode: BrowserSessionMode;
35
+ protected readonly transport: SessionTransport;
36
+ constructor(mode: BrowserSessionMode, transport: SessionTransport);
37
+ ensureReady(): Promise<void>;
38
+ openPage(url: string): Promise<PageHandle>;
39
+ listPages(): Promise<PageHandle[]>;
40
+ closePage(page: PageHandle): Promise<void>;
41
+ requestVisibleBrowser(reason: string): Promise<void>;
42
+ abstract getStatus(): Promise<BrowserStatus>;
43
+ shutdown(): Promise<void>;
44
+ }
45
+ /** Fresh: anonymous, stateless, headless. Never inherits auth (spec 12). */
46
+ export declare class FreshSession extends BaseSession {
47
+ constructor(transport: SessionTransport);
48
+ getStatus(): Promise<BrowserStatus>;
49
+ }
50
+ /** Events driving the Persistent state machine (spec section 2). */
51
+ export type PersistentEvent = 'bootstrap-needed' | 'bootstrap-opened' | 'bootstrap-closed' | 'automation-started' | 'automation-succeeded' | 'auth-required' | 'reauth-opened' | 'reauth-completed' | 'headless-incompatible';
52
+ /** Pure Persistent lifecycle transition. Returns the state unchanged for unknown events. */
53
+ export declare function nextPersistentState(state: PersistentState, event: PersistentEvent): PersistentState;
54
+ /** Normalize a URL or origin to a bare origin for preference lookup. */
55
+ export declare function normalizeOrigin(urlOrOrigin: string): string;
56
+ /** Resolve the execution mode for an origin or full URL (spec section 8). */
57
+ export declare function resolveExecutionForOrigin(preferences: SiteBrowserPreference[], urlOrOrigin: string, fallback?: PersistentExecutionMode): PersistentExecutionMode;
58
+ /** Remember/overwrite the per-origin preference; never downgrades globally. */
59
+ export declare function rememberExecutionPreference(preferences: SiteBrowserPreference[], urlOrOrigin: string, executionMode: PersistentExecutionMode): SiteBrowserPreference[];
60
+ export interface PersistentSessionOptions {
61
+ transport: SessionTransport;
62
+ metadata: PersistentBrowserMetadata;
63
+ initialState?: PersistentState;
64
+ executionMode?: PersistentExecutionMode;
65
+ sitePreferences?: SiteBrowserPreference[];
66
+ }
67
+ /**
68
+ * Persistent: Pi's browser identity. Headless first; per-origin
69
+ * headed-background fallback; reauth via headed browser (spec 2, 7, 8).
70
+ */
71
+ export declare class PersistentSession extends BaseSession {
72
+ private persistentState;
73
+ private executionMode;
74
+ private sitePreferences;
75
+ private metadata;
76
+ constructor(options: PersistentSessionOptions);
77
+ get persistentStatus(): PersistentState;
78
+ get currentExecutionMode(): PersistentExecutionMode;
79
+ get preferences(): SiteBrowserPreference[];
80
+ send(event: PersistentEvent): PersistentState;
81
+ executionFor(urlOrOrigin: string): PersistentExecutionMode;
82
+ /** A site failed headless while headed works: pin headed-background there. */
83
+ markHeadlessIncompatible(urlOrOrigin: string): void;
84
+ getStatus(): Promise<BrowserStatus>;
85
+ }
86
+ /**
87
+ * Existing: the user's browser identity via autoConnect (spec 13).
88
+ * All Pi-created tabs must go through the extension broker into the
89
+ * collapsed `pi-browser-use` group — never raw foreground tabs.
90
+ */
91
+ export declare class ExistingSession extends BaseSession {
92
+ constructor(transport: SessionTransport);
93
+ getStatus(): Promise<BrowserStatus>;
94
+ }
95
+ export interface ManagedSessions {
96
+ fresh: BrowserSession;
97
+ persistent: BrowserSession;
98
+ existing: BrowserSession;
99
+ }
100
+ /**
101
+ * Resolve a capability request to a mode (spec section 21):
102
+ * persistence/auth → persistent; explicit existing opt-in → existing;
103
+ * otherwise fresh. Callers escalate along the fallback hierarchies
104
+ * (sections 24/25) when the resolved mode cannot serve.
105
+ */
106
+ export declare function resolveModeForCapabilities(request: BrowserCapabilityRequest, persistentInitialized: boolean): BrowserSessionMode;
107
+ /** Persistent escalation sequence (spec section 24). */
108
+ export type PersistentEscalation = 'headless' | 'headed-auth-then-headless' | 'headed-background' | 'suggest-existing';
109
+ /** Next step when persistent headless cannot proceed. */
110
+ export declare function nextPersistentEscalation(reason: 'works' | 'login-needed' | 'headless-incompatible'): PersistentEscalation;
111
+ /** Existing-mode creation contract (spec section 25): fail loudly when the
112
+ * extension broker is unavailable rather than opening unmanaged tabs. */
113
+ export declare function assertExistingBrokerAvailable(available: boolean): void;
114
+ export declare class BrowserSessionManager {
115
+ private readonly sessions;
116
+ private current;
117
+ constructor(sessions: ManagedSessions);
118
+ getMode(): BrowserSessionMode;
119
+ getSession(mode?: BrowserSessionMode): BrowserSession;
120
+ switchTo(mode: BrowserSessionMode): Promise<BrowserSession>;
121
+ /** Capability-based selection (spec 21): skills ask, manager resolves. */
122
+ require(request: BrowserCapabilityRequest): Promise<BrowserSession>;
123
+ shutdownAll(): Promise<void>;
124
+ }
125
+ //# sourceMappingURL=session-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"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"}