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,275 @@
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 { PI_GROUP_TITLE } from './focus-policy.js';
21
+ /** In-memory transport for tests and for wiring custom backends. */
22
+ export function createMemoryTransport() {
23
+ const pages = [];
24
+ let counter = 0;
25
+ return {
26
+ pages,
27
+ async openPage(url) {
28
+ counter += 1;
29
+ const page = { id: `page-${counter}`, url };
30
+ pages.push(page);
31
+ return page;
32
+ },
33
+ async listPages() {
34
+ return [...pages];
35
+ },
36
+ async closePage(page) {
37
+ const index = pages.findIndex((p) => p.id === page.id);
38
+ if (index >= 0)
39
+ pages.splice(index, 1);
40
+ },
41
+ };
42
+ }
43
+ class BaseSession {
44
+ mode;
45
+ transport;
46
+ constructor(mode, transport) {
47
+ this.mode = mode;
48
+ this.transport = transport;
49
+ }
50
+ async ensureReady() { }
51
+ openPage(url) {
52
+ return this.transport.openPage(url);
53
+ }
54
+ listPages() {
55
+ return this.transport.listPages();
56
+ }
57
+ closePage(page) {
58
+ return this.transport.closePage(page);
59
+ }
60
+ async requestVisibleBrowser(reason) {
61
+ await this.transport.requestVisibleBrowser?.(reason);
62
+ }
63
+ async shutdown() { }
64
+ }
65
+ /** Fresh: anonymous, stateless, headless. Never inherits auth (spec 12). */
66
+ export class FreshSession extends BaseSession {
67
+ constructor(transport) {
68
+ super('fresh', transport);
69
+ }
70
+ async getStatus() {
71
+ return {
72
+ mode: 'fresh',
73
+ state: 'Running privately in background',
74
+ profile: 'Ephemeral (nothing persists)',
75
+ execution: 'Headless',
76
+ };
77
+ }
78
+ }
79
+ const PERSISTENT_TRANSITIONS = {
80
+ UNINITIALIZED: { 'bootstrap-needed': 'SETUP_REQUIRED' },
81
+ SETUP_REQUIRED: { 'bootstrap-opened': 'SETUP_HEADFUL' },
82
+ SETUP_HEADFUL: { 'bootstrap-closed': 'READY' },
83
+ READY: { 'automation-started': 'AUTOMATING_HEADLESS' },
84
+ AUTOMATING_HEADLESS: {
85
+ 'automation-succeeded': 'READY',
86
+ 'auth-required': 'REAUTH_REQUIRED',
87
+ 'headless-incompatible': 'AUTOMATING_HEADFUL',
88
+ },
89
+ AUTOMATING_HEADFUL: {
90
+ 'automation-succeeded': 'READY',
91
+ 'auth-required': 'REAUTH_REQUIRED',
92
+ },
93
+ REAUTH_REQUIRED: { 'reauth-opened': 'REAUTH_HEADFUL' },
94
+ REAUTH_HEADFUL: { 'reauth-completed': 'READY' },
95
+ };
96
+ /** Pure Persistent lifecycle transition. Returns the state unchanged for unknown events. */
97
+ export function nextPersistentState(state, event) {
98
+ return PERSISTENT_TRANSITIONS[state][event] ?? state;
99
+ }
100
+ /** Normalize a URL or origin to a bare origin for preference lookup. */
101
+ export function normalizeOrigin(urlOrOrigin) {
102
+ try {
103
+ return new URL(urlOrOrigin).origin;
104
+ }
105
+ catch {
106
+ return urlOrOrigin;
107
+ }
108
+ }
109
+ /** Resolve the execution mode for an origin or full URL (spec section 8). */
110
+ export function resolveExecutionForOrigin(preferences, urlOrOrigin, fallback = 'headless') {
111
+ const origin = normalizeOrigin(urlOrOrigin);
112
+ const match = preferences.find((p) => normalizeOrigin(p.origin) === origin);
113
+ return match?.executionMode ?? fallback;
114
+ }
115
+ /** Remember/overwrite the per-origin preference; never downgrades globally. */
116
+ export function rememberExecutionPreference(preferences, urlOrOrigin, executionMode) {
117
+ const origin = normalizeOrigin(urlOrOrigin);
118
+ const next = preferences.filter((p) => normalizeOrigin(p.origin) !== origin);
119
+ next.push({ origin, executionMode });
120
+ return next;
121
+ }
122
+ /**
123
+ * Persistent: Pi's browser identity. Headless first; per-origin
124
+ * headed-background fallback; reauth via headed browser (spec 2, 7, 8).
125
+ */
126
+ export class PersistentSession extends BaseSession {
127
+ persistentState;
128
+ executionMode;
129
+ sitePreferences;
130
+ metadata;
131
+ constructor(options) {
132
+ super('persistent', options.transport);
133
+ this.metadata = options.metadata;
134
+ this.persistentState =
135
+ options.initialState ?? (options.metadata.initialized ? 'READY' : 'SETUP_REQUIRED');
136
+ this.executionMode = options.executionMode ?? 'headless';
137
+ this.sitePreferences = [...(options.sitePreferences ?? [])];
138
+ }
139
+ get persistentStatus() {
140
+ return this.persistentState;
141
+ }
142
+ get currentExecutionMode() {
143
+ return this.executionMode;
144
+ }
145
+ get preferences() {
146
+ return [...this.sitePreferences];
147
+ }
148
+ send(event) {
149
+ this.persistentState = nextPersistentState(this.persistentState, event);
150
+ return this.persistentState;
151
+ }
152
+ executionFor(urlOrOrigin) {
153
+ try {
154
+ const origin = new URL(urlOrOrigin).origin;
155
+ return resolveExecutionForOrigin(this.sitePreferences, origin, this.executionMode);
156
+ }
157
+ catch {
158
+ return this.executionMode;
159
+ }
160
+ }
161
+ /** A site failed headless while headed works: pin headed-background there. */
162
+ markHeadlessIncompatible(urlOrOrigin) {
163
+ try {
164
+ const origin = new URL(urlOrOrigin).origin;
165
+ this.sitePreferences = rememberExecutionPreference(this.sitePreferences, origin, 'headed-background');
166
+ }
167
+ catch {
168
+ // Non-URL input: fall back to the session default without pinning.
169
+ this.executionMode = 'headed-background';
170
+ }
171
+ this.send('headless-incompatible');
172
+ }
173
+ async getStatus() {
174
+ const bootstrapped = this.metadata.initialized;
175
+ return {
176
+ mode: 'persistent',
177
+ state: this.persistentState === 'READY' || this.persistentState.startsWith('AUTOMATING')
178
+ ? 'Running privately in background'
179
+ : this.persistentState === 'REAUTH_REQUIRED' || this.persistentState === 'REAUTH_HEADFUL'
180
+ ? 'Authentication required'
181
+ : bootstrapped
182
+ ? 'Ready'
183
+ : 'Browser setup required',
184
+ profile: bootstrapped ? 'Ready' : 'Setup required',
185
+ execution: this.executionMode === 'headless' ? 'Headless' : 'Visible fallback (background)',
186
+ };
187
+ }
188
+ }
189
+ /**
190
+ * Existing: the user's browser identity via autoConnect (spec 13).
191
+ * All Pi-created tabs must go through the extension broker into the
192
+ * collapsed `pi-browser-use` group — never raw foreground tabs.
193
+ */
194
+ export class ExistingSession extends BaseSession {
195
+ constructor(transport) {
196
+ super('existing', transport);
197
+ }
198
+ async getStatus() {
199
+ return {
200
+ mode: 'existing',
201
+ state: 'Using your existing Chrome',
202
+ profile: 'Your browser',
203
+ execution: `Background tabs in “${PI_GROUP_TITLE}”`,
204
+ };
205
+ }
206
+ }
207
+ /**
208
+ * Resolve a capability request to a mode (spec section 21):
209
+ * persistence/auth → persistent; explicit existing opt-in → existing;
210
+ * otherwise fresh. Callers escalate along the fallback hierarchies
211
+ * (sections 24/25) when the resolved mode cannot serve.
212
+ */
213
+ export function resolveModeForCapabilities(request, persistentInitialized) {
214
+ if (request.persistence === true || request.authentication) {
215
+ return 'persistent';
216
+ }
217
+ if (request.supportsExisting === true && !persistentInitialized) {
218
+ return 'existing';
219
+ }
220
+ return 'fresh';
221
+ }
222
+ /** Next step when persistent headless cannot proceed. */
223
+ export function nextPersistentEscalation(reason) {
224
+ if (reason === 'works')
225
+ return 'headless';
226
+ if (reason === 'login-needed')
227
+ return 'headed-auth-then-headless';
228
+ return 'headed-background';
229
+ }
230
+ /** Existing-mode creation contract (spec section 25): fail loudly when the
231
+ * extension broker is unavailable rather than opening unmanaged tabs. */
232
+ export function assertExistingBrokerAvailable(available) {
233
+ if (!available) {
234
+ throw new Error(`Existing-mode tab broker unavailable: refusing to open unmanaged tabs. ` +
235
+ `Install the Pi extension so tabs land in the collapsed “${PI_GROUP_TITLE}” group.`);
236
+ }
237
+ }
238
+ export class BrowserSessionManager {
239
+ sessions;
240
+ current = 'fresh';
241
+ constructor(sessions) {
242
+ this.sessions = sessions;
243
+ }
244
+ getMode() {
245
+ return this.current;
246
+ }
247
+ getSession(mode = this.current) {
248
+ return this.sessions[mode];
249
+ }
250
+ async switchTo(mode) {
251
+ if (mode !== this.current) {
252
+ await this.sessions[this.current].shutdown().catch(() => { });
253
+ }
254
+ this.current = mode;
255
+ const session = this.sessions[mode];
256
+ await session.ensureReady();
257
+ return session;
258
+ }
259
+ /** Capability-based selection (spec 21): skills ask, manager resolves. */
260
+ async require(request) {
261
+ const persistent = this.sessions.persistent;
262
+ let initialized = false;
263
+ if (persistent instanceof PersistentSession) {
264
+ initialized = persistent.persistentStatus !== 'SETUP_REQUIRED';
265
+ }
266
+ const mode = resolveModeForCapabilities(request, initialized);
267
+ return this.switchTo(mode);
268
+ }
269
+ async shutdownAll() {
270
+ for (const session of Object.values(this.sessions)) {
271
+ await session.shutdown().catch(() => { });
272
+ }
273
+ }
274
+ }
275
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAuBlD,oEAAoE;AACpE,MAAM,UAAU,qBAAqB;IACnC,MAAM,KAAK,GAAiB,EAAE,CAAA;IAC9B,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,OAAO;QACL,KAAK;QACL,KAAK,CAAC,QAAQ,CAAC,GAAW;YACxB,OAAO,IAAI,CAAC,CAAA;YACZ,MAAM,IAAI,GAAe,EAAE,EAAE,EAAE,QAAQ,OAAO,EAAE,EAAE,GAAG,EAAE,CAAA;YACvD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAChB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,KAAK,CAAC,SAAS;YACb,OAAO,CAAC,GAAG,KAAK,CAAC,CAAA;QACnB,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,IAAgB;YAC9B,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAA;YACtD,IAAI,KAAK,IAAI,CAAC;gBAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACxC,CAAC;KACF,CAAA;AACH,CAAC;AAED,MAAe,WAAW;IAEb;IACU;IAFrB,YACW,IAAwB,EACd,SAA2B;QADrC,SAAI,GAAJ,IAAI,CAAoB;QACd,cAAS,GAAT,SAAS,CAAkB;IAC7C,CAAC;IAEJ,KAAK,CAAC,WAAW,KAAmB,CAAC;IACrC,QAAQ,CAAC,GAAW;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;IACrC,CAAC;IACD,SAAS;QACP,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,CAAA;IACnC,CAAC;IACD,SAAS,CAAC,IAAgB;QACxB,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IACvC,CAAC;IACD,KAAK,CAAC,qBAAqB,CAAC,MAAc;QACxC,MAAM,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC,CAAA;IACtD,CAAC;IAED,KAAK,CAAC,QAAQ,KAAmB,CAAC;CACnC;AAED,4EAA4E;AAC5E,MAAM,OAAO,YAAa,SAAQ,WAAW;IAC3C,YAAY,SAA2B;QACrC,KAAK,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IAC3B,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,iCAAiC;YACxC,OAAO,EAAE,8BAA8B;YACvC,SAAS,EAAE,UAAU;SACtB,CAAA;IACH,CAAC;CACF;AAcD,MAAM,sBAAsB,GAGxB;IACF,aAAa,EAAE,EAAE,kBAAkB,EAAE,gBAAgB,EAAE;IACvD,cAAc,EAAE,EAAE,kBAAkB,EAAE,eAAe,EAAE;IACvD,aAAa,EAAE,EAAE,kBAAkB,EAAE,OAAO,EAAE;IAC9C,KAAK,EAAE,EAAE,oBAAoB,EAAE,qBAAqB,EAAE;IACtD,mBAAmB,EAAE;QACnB,sBAAsB,EAAE,OAAO;QAC/B,eAAe,EAAE,iBAAiB;QAClC,uBAAuB,EAAE,oBAAoB;KAC9C;IACD,kBAAkB,EAAE;QAClB,sBAAsB,EAAE,OAAO;QAC/B,eAAe,EAAE,iBAAiB;KACnC;IACD,eAAe,EAAE,EAAE,eAAe,EAAE,gBAAgB,EAAE;IACtD,cAAc,EAAE,EAAE,kBAAkB,EAAE,OAAO,EAAE;CAChD,CAAA;AAED,4FAA4F;AAC5F,MAAM,UAAU,mBAAmB,CACjC,KAAsB,EACtB,KAAsB;IAEtB,OAAO,sBAAsB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,CAAA;AACtD,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,eAAe,CAAC,WAAmB;IACjD,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAA;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAA;IACpB,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,yBAAyB,CACvC,WAAoC,EACpC,WAAmB,EACnB,WAAoC,UAAU;IAE9C,MAAM,MAAM,GAAG,eAAe,CAAC,WAAW,CAAC,CAAA;IAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,CAAA;IAC3E,OAAO,KAAK,EAAE,aAAa,IAAI,QAAQ,CAAA;AACzC,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,2BAA2B,CACzC,WAAoC,EACpC,WAAmB,EACnB,aAAsC;IAEtC,MAAM,MAAM,GAAG,eAAe,CAAC,WAAW,CAAC,CAAA;IAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,CAAA;IAC5E,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAA;IACpC,OAAO,IAAI,CAAA;AACb,CAAC;AAUD;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IACxC,eAAe,CAAiB;IAChC,aAAa,CAAyB;IACtC,eAAe,CAAyB;IACxC,QAAQ,CAA2B;IAE3C,YAAY,OAAiC;QAC3C,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;QACtC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;QAChC,IAAI,CAAC,eAAe;YAClB,OAAO,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAA;QACrF,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,UAAU,CAAA;QACxD,IAAI,CAAC,eAAe,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,CAAA;IAC7D,CAAC;IAED,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,eAAe,CAAA;IAC7B,CAAC;IAED,IAAI,oBAAoB;QACtB,OAAO,IAAI,CAAC,aAAa,CAAA;IAC3B,CAAC;IAED,IAAI,WAAW;QACb,OAAO,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,CAAA;IAClC,CAAC;IAED,IAAI,CAAC,KAAsB;QACzB,IAAI,CAAC,eAAe,GAAG,mBAAmB,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,CAAA;QACvE,OAAO,IAAI,CAAC,eAAe,CAAA;IAC7B,CAAC;IAED,YAAY,CAAC,WAAmB;QAC9B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAA;YAC1C,OAAO,yBAAyB,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,CAAA;QACpF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,aAAa,CAAA;QAC3B,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,wBAAwB,CAAC,WAAmB;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAA;YAC1C,IAAI,CAAC,eAAe,GAAG,2BAA2B,CAChD,IAAI,CAAC,eAAe,EACpB,MAAM,EACN,mBAAmB,CACpB,CAAA;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;YACnE,IAAI,CAAC,aAAa,GAAG,mBAAmB,CAAA;QAC1C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAA;QAC9C,OAAO;YACL,IAAI,EAAE,YAAY;YAClB,KAAK,EACH,IAAI,CAAC,eAAe,KAAK,OAAO,IAAI,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,YAAY,CAAC;gBAC/E,CAAC,CAAC,iCAAiC;gBACnC,CAAC,CAAC,IAAI,CAAC,eAAe,KAAK,iBAAiB,IAAI,IAAI,CAAC,eAAe,KAAK,gBAAgB;oBACvF,CAAC,CAAC,yBAAyB;oBAC3B,CAAC,CAAC,YAAY;wBACZ,CAAC,CAAC,OAAO;wBACT,CAAC,CAAC,wBAAwB;YAClC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB;YAClD,SAAS,EAAE,IAAI,CAAC,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,+BAA+B;SAC5F,CAAA;IACH,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,eAAgB,SAAQ,WAAW;IAC9C,YAAY,SAA2B;QACrC,KAAK,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,4BAA4B;YACnC,OAAO,EAAE,cAAc;YACvB,SAAS,EAAE,uBAAuB,cAAc,GAAG;SACpD,CAAA;IACH,CAAC;CACF;AAQD;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAiC,EACjC,qBAA8B;IAE9B,IAAI,OAAO,CAAC,WAAW,KAAK,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QAC3D,OAAO,YAAY,CAAA;IACrB,CAAC;IACD,IAAI,OAAO,CAAC,gBAAgB,KAAK,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAChE,OAAO,UAAU,CAAA;IACnB,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAMD,yDAAyD;AACzD,MAAM,UAAU,wBAAwB,CACtC,MAA0D;IAE1D,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,UAAU,CAAA;IACzC,IAAI,MAAM,KAAK,cAAc;QAAE,OAAO,2BAA2B,CAAA;IACjE,OAAO,mBAAmB,CAAA;AAC5B,CAAC;AAED;yEACyE;AACzE,MAAM,UAAU,6BAA6B,CAAC,SAAkB;IAC9D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,yEAAyE;YACvE,2DAA2D,cAAc,UAAU,CACtF,CAAA;IACH,CAAC;AACH,CAAC;AAED,MAAM,OAAO,qBAAqB;IAGH;IAFrB,OAAO,GAAuB,OAAO,CAAA;IAE7C,YAA6B,QAAyB;QAAzB,aAAQ,GAAR,QAAQ,CAAiB;IAAG,CAAC;IAE1D,OAAO;QACL,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,UAAU,CAAC,OAA2B,IAAI,CAAC,OAAO;QAChD,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAwB;QACrC,IAAI,IAAI,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YAC1B,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC9D,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACnC,MAAM,OAAO,CAAC,WAAW,EAAE,CAAA;QAC3B,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,0EAA0E;IAC1E,KAAK,CAAC,OAAO,CAAC,OAAiC;QAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAA;QAC3C,IAAI,WAAW,GAAG,KAAK,CAAA;QACvB,IAAI,UAAU,YAAY,iBAAiB,EAAE,CAAC;YAC5C,WAAW,GAAG,UAAU,CAAC,gBAAgB,KAAK,gBAAgB,CAAA;QAChE,CAAC;QACD,MAAM,IAAI,GAAG,0BAA0B,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,WAAW;QACf,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnD,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC1C,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Stable internal browser API shared by all Pi browser modes.
3
+ *
4
+ * Skills talk to {@link BrowserSession} only. They must never deal with
5
+ * Chrome process flags, profile directories, CDP endpoints, tab-group IDs,
6
+ * or focus behavior directly — that translation lives in
7
+ * `BrowserSessionManager` (see `session-manager.ts`).
8
+ *
9
+ * Spec sections: 1 (core architecture), 2 (persistent metadata),
10
+ * 6 (skill-owned auth detection), 8 (execution modes), 21 (capabilities),
11
+ * 23 (status UX).
12
+ */
13
+ export type BrowserSessionMode = 'fresh' | 'persistent' | 'existing';
14
+ /** Opaque handle to an open page/tab. Backends resolve it to MCP/CDP state. */
15
+ export interface PageHandle {
16
+ /** Backend page identifier (MCP pageId, CDP target id, ...). */
17
+ id: string;
18
+ url?: string;
19
+ title?: string;
20
+ }
21
+ /** User-facing browser status. Never expose CDP/MCP terminology here. */
22
+ export interface BrowserStatus {
23
+ mode: BrowserSessionMode;
24
+ /** Plain-language state, e.g. "Running privately in background". */
25
+ state: string;
26
+ /** e.g. "Ready", "Setup required", "Authentication required". */
27
+ profile: string;
28
+ /** e.g. "Headless", "Visible fallback", "Using your existing Chrome". */
29
+ execution: string;
30
+ }
31
+ export interface BrowserSession {
32
+ readonly mode: BrowserSessionMode;
33
+ ensureReady(): Promise<void>;
34
+ openPage(url: string): Promise<PageHandle>;
35
+ listPages(): Promise<PageHandle[]>;
36
+ closePage(page: PageHandle): Promise<void>;
37
+ /**
38
+ * Ask to make the browser visible (auth handoff, explicit "show me").
39
+ * Implementations may no-op when already visible or when the mode is
40
+ * headless-only.
41
+ */
42
+ requestVisibleBrowser(reason: string): Promise<void>;
43
+ getStatus(): Promise<BrowserStatus>;
44
+ shutdown(): Promise<void>;
45
+ }
46
+ /**
47
+ * Thrown by skill-level auth verifiers when a page needs a human
48
+ * (sign-in, 2FA, passkey, CAPTCHA, SSO). The browser subsystem catches this
49
+ * and moves the Persistent session into reauthentication; skills define the
50
+ * destination URL and the authenticated/challenge checks.
51
+ */
52
+ export declare class BrowserAuthRequired extends Error {
53
+ readonly provider: string;
54
+ readonly url?: string;
55
+ constructor(options: {
56
+ provider: string;
57
+ url?: string;
58
+ message?: string;
59
+ });
60
+ }
61
+ /** Two automation execution modes inside Persistent (spec section 8). */
62
+ export type PersistentExecutionMode = 'headless' | 'headed-background';
63
+ /** Persistent lifecycle state machine (spec section 2). */
64
+ export type PersistentState = 'UNINITIALIZED' | 'SETUP_REQUIRED' | 'SETUP_HEADFUL' | 'READY' | 'AUTOMATING_HEADLESS' | 'AUTOMATING_HEADFUL' | 'REAUTH_REQUIRED' | 'REAUTH_HEADFUL';
65
+ /**
66
+ * Durable Persistent state. Passwords, cookies, tokens, and copied browser
67
+ * credentials must never be stored here — Chrome owns those inside its
68
+ * profile directory.
69
+ */
70
+ export interface PersistentBrowserMetadata {
71
+ initialized: boolean;
72
+ profilePath: string;
73
+ lastSuccessfulMode?: 'headless' | 'headed';
74
+ lastBootstrapAt?: string;
75
+ }
76
+ /** Optional per-origin headed-background preference (spec section 8). */
77
+ export interface SiteBrowserPreference {
78
+ origin: string;
79
+ executionMode: PersistentExecutionMode;
80
+ }
81
+ /** Capability intent from a skill (spec section 21). */
82
+ export interface BrowserCapabilityRequest {
83
+ /** True when cookies/sessions must survive restarts. */
84
+ persistence?: boolean;
85
+ /** e.g. "gmail", "github" — informational, used for status/reauth UX. */
86
+ authentication?: string;
87
+ /** Default: prefer headless, fall back to headed-background per origin. */
88
+ visibility?: 'prefer-headless' | 'require-headless' | 'allow-visible';
89
+ /** Whether falling back to the user's own Chrome is acceptable. */
90
+ supportsExisting?: boolean;
91
+ }
92
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,YAAY,GAAG,UAAU,CAAA;AAEpE,+EAA+E;AAC/E,MAAM,WAAW,UAAU;IACzB,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,kBAAkB,CAAA;IACxB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAA;IACb,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAA;IACf,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAA;IAEjC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IAC1C,SAAS,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IAClC,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1C;;;;OAIG;IACH,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC,CAAA;IACnC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;gBAET,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;CAM1E;AAED,yEAAyE;AACzE,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG,mBAAmB,CAAA;AAEtE,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GACvB,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,OAAO,GACP,qBAAqB,GACrB,oBAAoB,GACpB,iBAAiB,GACjB,gBAAgB,CAAA;AAEpB;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,OAAO,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,kBAAkB,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;IAC1C,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,yEAAyE;AACzE,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,uBAAuB,CAAA;CACvC;AAED,wDAAwD;AACxD,MAAM,WAAW,wBAAwB;IACvC,wDAAwD;IACxD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,iBAAiB,GAAG,kBAAkB,GAAG,eAAe,CAAA;IACrE,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Stable internal browser API shared by all Pi browser modes.
3
+ *
4
+ * Skills talk to {@link BrowserSession} only. They must never deal with
5
+ * Chrome process flags, profile directories, CDP endpoints, tab-group IDs,
6
+ * or focus behavior directly — that translation lives in
7
+ * `BrowserSessionManager` (see `session-manager.ts`).
8
+ *
9
+ * Spec sections: 1 (core architecture), 2 (persistent metadata),
10
+ * 6 (skill-owned auth detection), 8 (execution modes), 21 (capabilities),
11
+ * 23 (status UX).
12
+ */
13
+ /**
14
+ * Thrown by skill-level auth verifiers when a page needs a human
15
+ * (sign-in, 2FA, passkey, CAPTCHA, SSO). The browser subsystem catches this
16
+ * and moves the Persistent session into reauthentication; skills define the
17
+ * destination URL and the authenticated/challenge checks.
18
+ */
19
+ export class BrowserAuthRequired extends Error {
20
+ provider;
21
+ url;
22
+ constructor(options) {
23
+ super(options.message ?? `Authentication required (provider: ${options.provider})`);
24
+ this.name = 'BrowserAuthRequired';
25
+ this.provider = options.provider;
26
+ this.url = options.url;
27
+ }
28
+ }
29
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAwCH;;;;;GAKG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,QAAQ,CAAQ;IAChB,GAAG,CAAS;IAErB,YAAY,OAA6D;QACvE,KAAK,CAAC,OAAO,CAAC,OAAO,IAAI,sCAAsC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACnF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAA;QACjC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;QAChC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAA;IACxB,CAAC;CACF"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Persistent bootstrap and reauthentication flows (spec sections 3 and 7).
3
+ *
4
+ * Bootstrap (first run): launch a real headed Chrome on the Pi profile with
5
+ * no MCP/Puppeteer/CDP — an ordinary manually launched browser. The user
6
+ * signs into Chrome/Google and any sites, completes 2FA/passkeys/SSO, then
7
+ * closes the window. Close means SETUP_HEADFUL → READY; it initializes the
8
+ * *profile*, it does not prove every site is authenticated (auth stays
9
+ * site-specific, verified by skill-level verifiers).
10
+ *
11
+ * Reauthentication: when a skill raises BrowserAuthRequired, shut the
12
+ * headless backend down cleanly, then reauth in one of two variants:
13
+ * - Variant B (default): Pi-owned headed Chrome *with* CDP, so Pi can
14
+ * navigate to the login page before handing control to the user.
15
+ * - Variant A (fallback): plain headed Chrome with no MCP/CDP, for login
16
+ * providers that reject instrumented browsers.
17
+ * Afterwards the backend restarts headless and automation resumes.
18
+ *
19
+ * Launchers are injectable so the orchestration is unit-testable.
20
+ */
21
+ import type { PersistentBackend } from './persistent-backend.js';
22
+ export type ReauthVariant = 'instrumented' | 'plain';
23
+ export interface SetupFlowEvents {
24
+ /** Human-facing instruction shown before the setup window opens. */
25
+ onSetupNeeded?: (message: string) => void;
26
+ /** Fired when the setup browser exits and the profile is marked ready. */
27
+ onSetupComplete?: (profileDir: string) => void;
28
+ onReauthNeeded?: (message: string) => void;
29
+ onReauthComplete?: (profileDir: string) => void;
30
+ }
31
+ export declare const SETUP_INSTRUCTIONS: string;
32
+ export declare function reauthInstructions(url: string, variant: ReauthVariant): string;
33
+ /**
34
+ * First-run bootstrap. Holds no locks itself — the caller (browser_setup
35
+ * tool) must ensure no backend is running on the profile. Resolves with the
36
+ * window exit code after marking the profile initialized.
37
+ */
38
+ export declare function runBootstrap(options: {
39
+ profileDir?: string;
40
+ executablePath?: string;
41
+ chromeArgs?: string[];
42
+ launch?: (options: {
43
+ userDataDir: string;
44
+ profileDirectory?: string;
45
+ executablePath?: string;
46
+ chromeArgs?: string[];
47
+ }) => Promise<number | null>;
48
+ }, events?: SetupFlowEvents): Promise<number | null>;
49
+ export interface ReauthOptions {
50
+ backend: PersistentBackend;
51
+ /** Page that needs auth (used for messaging + Variant B navigation hint). */
52
+ url: string;
53
+ variant?: ReauthVariant;
54
+ /** Plain-variant launcher (no CDP). Defaults to launchSetupBrowser. */
55
+ launchPlain?: (options: {
56
+ userDataDir: string;
57
+ profileDirectory?: string;
58
+ executablePath?: string;
59
+ chromeArgs?: string[];
60
+ }) => Promise<number | null>;
61
+ /** Restart the backend headed/headless (Variant B + resume). */
62
+ restartBackend?: (headed: boolean) => Promise<unknown>;
63
+ events?: SetupFlowEvents;
64
+ }
65
+ /**
66
+ * Run reauthentication against a stopped backend: the caller must have
67
+ * already shut the headless backend down (or pass a backend whose
68
+ * restartBackend handles it). Variant B restarts headed with CDP and leaves
69
+ * the headed backend running for the handoff; Variant A opens a plain window
70
+ * and waits for close. Returns the user-facing instruction to relay.
71
+ */
72
+ export declare function runReauth(options: ReauthOptions): Promise<string>;
73
+ /**
74
+ * Resume headless automation after reauth: restart the backend headless.
75
+ * Returns true when the backend reports running afterwards.
76
+ */
77
+ export declare function resumeHeadless(backend: PersistentBackend): Promise<boolean>;
78
+ //# sourceMappingURL=setup-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-flow.d.ts","sourceRoot":"","sources":["../src/setup-flow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAIhE,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,OAAO,CAAA;AAEpD,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,0EAA0E;IAC1E,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9C,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAChD;AAED,eAAO,MAAM,kBAAkB,QAKnB,CAAA;AAEZ,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAU9E;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE;IACP,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;QACjB,WAAW,EAAE,MAAM,CAAA;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;QACzB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;KACtB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CAC7B,EACD,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAexB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,iBAAiB,CAAA;IAC1B,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,uEAAuE;IACvE,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE;QACtB,WAAW,EAAE,MAAM,CAAA;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;QACzB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;KACtB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC5B,gEAAgE;IAChE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACtD,MAAM,CAAC,EAAE,eAAe,CAAA;CACzB;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBvE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAGjF"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Persistent bootstrap and reauthentication flows (spec sections 3 and 7).
3
+ *
4
+ * Bootstrap (first run): launch a real headed Chrome on the Pi profile with
5
+ * no MCP/Puppeteer/CDP — an ordinary manually launched browser. The user
6
+ * signs into Chrome/Google and any sites, completes 2FA/passkeys/SSO, then
7
+ * closes the window. Close means SETUP_HEADFUL → READY; it initializes the
8
+ * *profile*, it does not prove every site is authenticated (auth stays
9
+ * site-specific, verified by skill-level verifiers).
10
+ *
11
+ * Reauthentication: when a skill raises BrowserAuthRequired, shut the
12
+ * headless backend down cleanly, then reauth in one of two variants:
13
+ * - Variant B (default): Pi-owned headed Chrome *with* CDP, so Pi can
14
+ * navigate to the login page before handing control to the user.
15
+ * - Variant A (fallback): plain headed Chrome with no MCP/CDP, for login
16
+ * providers that reject instrumented browsers.
17
+ * Afterwards the backend restarts headless and automation resumes.
18
+ *
19
+ * Launchers are injectable so the orchestration is unit-testable.
20
+ */
21
+ import { launchChrome, launchSetupBrowser } from './chrome-launcher.js';
22
+ import { ensureNamedProfile, PI_PROFILE_NAME } from './named-profile.js';
23
+ import { markBootstrapped } from './persistent-store.js';
24
+ import { DEFAULT_PROFILE_DIR } from './config.js';
25
+ export const SETUP_INSTRUCTIONS = [
26
+ 'Set up Pi Browser',
27
+ '',
28
+ 'Sign into Google and any websites you want Pi to use.',
29
+ "When you're finished, close the Pi Browser window.",
30
+ ].join('\n');
31
+ export function reauthInstructions(url, variant) {
32
+ const base = variant === 'plain'
33
+ ? 'a plain browser window just opened (no automation attached)'
34
+ : 'a browser window just opened on the Pi profile';
35
+ return [
36
+ `Pi needs you to verify your account for ${url}: ${base}.`,
37
+ 'Complete the sign-in / verification step in that window.',
38
+ 'When you are done, close the window (plain variant) or tell the agent to continue.',
39
+ ].join('\n');
40
+ }
41
+ /**
42
+ * First-run bootstrap. Holds no locks itself — the caller (browser_setup
43
+ * tool) must ensure no backend is running on the profile. Resolves with the
44
+ * window exit code after marking the profile initialized.
45
+ */
46
+ export async function runBootstrap(options, events) {
47
+ const profileDir = options.profileDir ?? DEFAULT_PROFILE_DIR;
48
+ events?.onSetupNeeded?.(SETUP_INSTRUCTIONS);
49
+ // Same named identity automation uses: sign in here, automate there.
50
+ ensureNamedProfile(profileDir);
51
+ const launch = options.launch ?? launchSetupBrowser;
52
+ const code = await launch({
53
+ userDataDir: profileDir,
54
+ profileDirectory: PI_PROFILE_NAME,
55
+ executablePath: options.executablePath,
56
+ chromeArgs: options.chromeArgs,
57
+ });
58
+ markBootstrapped(profileDir);
59
+ events?.onSetupComplete?.(profileDir);
60
+ return code;
61
+ }
62
+ /**
63
+ * Run reauthentication against a stopped backend: the caller must have
64
+ * already shut the headless backend down (or pass a backend whose
65
+ * restartBackend handles it). Variant B restarts headed with CDP and leaves
66
+ * the headed backend running for the handoff; Variant A opens a plain window
67
+ * and waits for close. Returns the user-facing instruction to relay.
68
+ */
69
+ export async function runReauth(options) {
70
+ const variant = options.variant ?? 'instrumented';
71
+ const profileDir = options.backend.profileDir?.() ?? DEFAULT_PROFILE_DIR;
72
+ const message = reauthInstructions(options.url, variant);
73
+ options.events?.onReauthNeeded?.(message);
74
+ if (variant === 'plain') {
75
+ const launch = options.launchPlain ?? launchSetupBrowser;
76
+ await launch({ userDataDir: profileDir, profileDirectory: PI_PROFILE_NAME });
77
+ }
78
+ else {
79
+ if (options.restartBackend) {
80
+ await options.restartBackend(true);
81
+ }
82
+ else {
83
+ await options.backend.restart(true);
84
+ }
85
+ }
86
+ options.events?.onReauthComplete?.(profileDir);
87
+ return message;
88
+ }
89
+ /**
90
+ * Resume headless automation after reauth: restart the backend headless.
91
+ * Returns true when the backend reports running afterwards.
92
+ */
93
+ export async function resumeHeadless(backend) {
94
+ await backend.restart(false);
95
+ return backend.running();
96
+ }
97
+ //# sourceMappingURL=setup-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-flow.js","sourceRoot":"","sources":["../src/setup-flow.ts"],"names":[],"mappings":"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"}