@apitap/core 1.0.14 → 1.0.15

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.
@@ -25,9 +25,13 @@ export declare function hasHighConfidenceAuthTransition(baselineCookieValues: Ma
25
25
  * Flow:
26
26
  * 1. Launch visible Chromium browser
27
27
  * 2. Navigate to login URL
28
- * 3. Wait for human to log in (watches for session cookies / auth headers)
29
- * 4. Capture all cookies + detected auth
28
+ * 3. Wait for human to log in and close the browser
29
+ * 4. Capture all cookies + detected auth from last snapshot
30
30
  * 5. Store encrypted via AuthManager
31
- * 6. Close browser, return result
31
+ * 6. Return result
32
+ *
33
+ * The user closing the browser is the primary signal that login is complete.
34
+ * This avoids false positives from cookie-based heuristics that fire on
35
+ * anonymous session cookies set during normal page load.
32
36
  */
33
37
  export declare function requestAuth(authManager: AuthManager, options: HandoffOptions): Promise<HandoffResult>;
@@ -68,10 +68,14 @@ const handoffLocks = new Map();
68
68
  * Flow:
69
69
  * 1. Launch visible Chromium browser
70
70
  * 2. Navigate to login URL
71
- * 3. Wait for human to log in (watches for session cookies / auth headers)
72
- * 4. Capture all cookies + detected auth
71
+ * 3. Wait for human to log in and close the browser
72
+ * 4. Capture all cookies + detected auth from last snapshot
73
73
  * 5. Store encrypted via AuthManager
74
- * 6. Close browser, return result
74
+ * 6. Return result
75
+ *
76
+ * The user closing the browser is the primary signal that login is complete.
77
+ * This avoids false positives from cookie-based heuristics that fire on
78
+ * anonymous session cookies set during normal page load.
75
79
  */
76
80
  export async function requestAuth(authManager, options) {
77
81
  const { domain } = options;
@@ -102,13 +106,9 @@ async function doHandoff(authManager, options) {
102
106
  const page = await context.newPage();
103
107
  let authDetected;
104
108
  let detectedAuth;
105
- // Watch network responses for auth signals
109
+ let latestCookies = [];
110
+ // Watch network responses for auth signals (bearer tokens, API keys)
106
111
  page.on('response', (response) => {
107
- const headers = new Map();
108
- for (const [key, value] of Object.entries(response.headers())) {
109
- headers.set(key, value);
110
- }
111
- // Detect auth from request headers
112
112
  const authHeader = response.request().headers()['authorization'];
113
113
  if (authHeader) {
114
114
  if (authHeader.startsWith('Bearer ')) {
@@ -131,44 +131,39 @@ async function doHandoff(authManager, options) {
131
131
  });
132
132
  // Navigate to login page
133
133
  await page.goto(loginUrl, { waitUntil: 'domcontentloaded', timeout: 30_000 });
134
- // Let the page settle many sites set cookies via async JS after domcontentloaded.
135
- // Wait for network to go idle (or timeout after 5s), then pause 3s more for late cookies.
136
- // Without this, pre-login cookies trigger false positive auth transitions.
137
- await page.waitForLoadState('networkidle', { timeout: 5_000 }).catch(() => { });
138
- await page.waitForTimeout(3_000);
139
- // Baseline: snapshot cookie values AFTER the page has fully settled
140
- const baselineCookies = await context.cookies();
141
- const baselineCookieValues = new Map(baselineCookies.map(c => [c.name, c.value]));
142
- // Poll for login success: check for NEW session-like cookies
143
- const startTime = Date.now();
144
- let loginDetected = false;
145
- while (Date.now() - startTime < timeout) {
146
- await page.waitForTimeout(2000);
147
- const cookies = await context.cookies();
148
- const hasAuthTransition = hasHighConfidenceAuthTransition(baselineCookieValues, cookies);
149
- if (hasAuthTransition || authDetected) {
150
- // Grace period: 4 additional polls at 2s each (~8s total)
151
- // Allows time for MFA, CAPTCHAs, and post-login redirects
152
- for (let grace = 0; grace < 4; grace++) {
153
- if (page.isClosed())
154
- break;
155
- await page.waitForLoadState('networkidle', { timeout: 3000 }).catch(() => { });
156
- await page.waitForTimeout(2000);
157
- }
158
- loginDetected = true;
159
- break;
134
+ // Continuously snapshot cookies so we have the latest when browser closes.
135
+ // We can't read cookies after the browser disconnects.
136
+ const cookieInterval = setInterval(async () => {
137
+ try {
138
+ latestCookies = await context.cookies();
139
+ }
140
+ catch {
141
+ // Browser may be closing keep last snapshot
160
142
  }
161
- // Check if browser was closed by user
162
- if (page.isClosed())
163
- break;
143
+ }, 2000);
144
+ // Wait for user to close browser (primary signal) or timeout.
145
+ // The user logs in at their own pace, then closes the browser when done.
146
+ await new Promise((resolve) => {
147
+ const timer = setTimeout(resolve, timeout);
148
+ browser.on('disconnected', () => {
149
+ clearTimeout(timer);
150
+ resolve();
151
+ });
152
+ });
153
+ clearInterval(cookieInterval);
154
+ // Try to get final cookies (may fail if browser already disconnected)
155
+ try {
156
+ latestCookies = await context.cookies();
157
+ }
158
+ catch {
159
+ // Browser disconnected — use last snapshot from interval
164
160
  }
165
- // Capture final cookies
166
- const cookies = await context.cookies();
161
+ const cookies = latestCookies;
167
162
  if (cookies.length === 0 && !authDetected) {
168
163
  return {
169
164
  success: false,
170
165
  cookieCount: 0,
171
- error: loginDetected ? undefined : 'Timeout: no login detected within the allowed time',
166
+ error: 'No cookies captured. Browser may have been closed before page loaded.',
172
167
  };
173
168
  }
174
169
  // Store session cookies
@@ -213,7 +208,12 @@ async function doHandoff(authManager, options) {
213
208
  };
214
209
  }
215
210
  finally {
216
- await browser.close();
211
+ try {
212
+ await browser.close();
213
+ }
214
+ catch {
215
+ // Browser already disconnected by user
216
+ }
217
217
  }
218
218
  }
219
219
  //# sourceMappingURL=handoff.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handoff.js","sourceRoot":"","sources":["../../src/auth/handoff.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"handoff.js","sourceRoot":"","sources":["../../src/auth/handoff.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apitap/core",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "description": "Intercept web API traffic during browsing. Generate portable skill files so AI agents can call APIs directly instead of scraping.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -98,10 +98,14 @@ const handoffLocks = new Map<string, Promise<HandoffResult>>();
98
98
  * Flow:
99
99
  * 1. Launch visible Chromium browser
100
100
  * 2. Navigate to login URL
101
- * 3. Wait for human to log in (watches for session cookies / auth headers)
102
- * 4. Capture all cookies + detected auth
101
+ * 3. Wait for human to log in and close the browser
102
+ * 4. Capture all cookies + detected auth from last snapshot
103
103
  * 5. Store encrypted via AuthManager
104
- * 6. Close browser, return result
104
+ * 6. Return result
105
+ *
106
+ * The user closing the browser is the primary signal that login is complete.
107
+ * This avoids false positives from cookie-based heuristics that fire on
108
+ * anonymous session cookies set during normal page load.
105
109
  */
106
110
  export async function requestAuth(
107
111
  authManager: AuthManager,
@@ -144,15 +148,10 @@ async function doHandoff(
144
148
  const page = await context.newPage();
145
149
  let authDetected: 'bearer' | 'cookie' | 'api-key' | undefined;
146
150
  let detectedAuth: StoredAuth | undefined;
151
+ let latestCookies: Array<{ name: string; value: string; domain: string; path: string; expires: number; httpOnly: boolean; secure: boolean; sameSite: 'Strict' | 'Lax' | 'None' }> = [];
147
152
 
148
- // Watch network responses for auth signals
153
+ // Watch network responses for auth signals (bearer tokens, API keys)
149
154
  page.on('response', (response) => {
150
- const headers = new Map<string, string>();
151
- for (const [key, value] of Object.entries(response.headers())) {
152
- headers.set(key, value);
153
- }
154
-
155
- // Detect auth from request headers
156
155
  const authHeader = response.request().headers()['authorization'];
157
156
  if (authHeader) {
158
157
  if (authHeader.startsWith('Bearer ')) {
@@ -176,52 +175,42 @@ async function doHandoff(
176
175
  // Navigate to login page
177
176
  await page.goto(loginUrl, { waitUntil: 'domcontentloaded', timeout: 30_000 });
178
177
 
179
- // Let the page settle many sites set cookies via async JS after domcontentloaded.
180
- // Wait for network to go idle (or timeout after 5s), then pause 3s more for late cookies.
181
- // Without this, pre-login cookies trigger false positive auth transitions.
182
- await page.waitForLoadState('networkidle', { timeout: 5_000 }).catch(() => {});
183
- await page.waitForTimeout(3_000);
184
-
185
- // Baseline: snapshot cookie values AFTER the page has fully settled
186
- const baselineCookies = await context.cookies();
187
- const baselineCookieValues = new Map(
188
- baselineCookies.map(c => [c.name, c.value])
189
- );
190
-
191
- // Poll for login success: check for NEW session-like cookies
192
- const startTime = Date.now();
193
- let loginDetected = false;
194
-
195
- while (Date.now() - startTime < timeout) {
196
- await page.waitForTimeout(2000);
197
-
198
- const cookies = await context.cookies();
199
- const hasAuthTransition = hasHighConfidenceAuthTransition(baselineCookieValues, cookies);
200
-
201
- if (hasAuthTransition || authDetected) {
202
- // Grace period: 4 additional polls at 2s each (~8s total)
203
- // Allows time for MFA, CAPTCHAs, and post-login redirects
204
- for (let grace = 0; grace < 4; grace++) {
205
- if (page.isClosed()) break;
206
- await page.waitForLoadState('networkidle', { timeout: 3000 }).catch(() => {});
207
- await page.waitForTimeout(2000);
208
- }
209
- loginDetected = true;
210
- break;
178
+ // Continuously snapshot cookies so we have the latest when browser closes.
179
+ // We can't read cookies after the browser disconnects.
180
+ const cookieInterval = setInterval(async () => {
181
+ try {
182
+ latestCookies = await context.cookies();
183
+ } catch {
184
+ // Browser may be closing keep last snapshot
211
185
  }
186
+ }, 2000);
187
+
188
+ // Wait for user to close browser (primary signal) or timeout.
189
+ // The user logs in at their own pace, then closes the browser when done.
190
+ await new Promise<void>((resolve) => {
191
+ const timer = setTimeout(resolve, timeout);
192
+ browser.on('disconnected', () => {
193
+ clearTimeout(timer);
194
+ resolve();
195
+ });
196
+ });
197
+
198
+ clearInterval(cookieInterval);
212
199
 
213
- // Check if browser was closed by user
214
- if (page.isClosed()) break;
200
+ // Try to get final cookies (may fail if browser already disconnected)
201
+ try {
202
+ latestCookies = await context.cookies();
203
+ } catch {
204
+ // Browser disconnected — use last snapshot from interval
215
205
  }
216
206
 
217
- // Capture final cookies
218
- const cookies = await context.cookies();
207
+ const cookies = latestCookies;
219
208
 
220
209
  if (cookies.length === 0 && !authDetected) {
221
210
  return {
222
211
  success: false,
223
212
  cookieCount: 0,
224
- error: loginDetected ? undefined : 'Timeout: no login detected within the allowed time',
213
+ error: 'No cookies captured. Browser may have been closed before page loaded.',
225
214
  };
226
215
  }
227
216
 
@@ -267,6 +256,10 @@ async function doHandoff(
267
256
  error: error instanceof Error ? error.message : String(error),
268
257
  };
269
258
  } finally {
270
- await browser.close();
259
+ try {
260
+ await browser.close();
261
+ } catch {
262
+ // Browser already disconnected by user
263
+ }
271
264
  }
272
265
  }