@apitap/core 1.5.3 → 1.5.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  # ApiTap
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@apitap/core)](https://www.npmjs.com/package/@apitap/core)
4
- [![tests](https://img.shields.io/badge/tests-1172%20passing-brightgreen)](https://github.com/n1byn1kt/apitap)
4
+ [![tests](https://img.shields.io/badge/tests-1195%20passing-brightgreen)](https://github.com/n1byn1kt/apitap)
5
5
  [![license](https://img.shields.io/badge/license-BSL--1.1-blue)](./LICENSE)
6
6
 
7
7
  **The MCP server that turns any website into an API — no docs, no SDK, no browser.**
@@ -34,13 +34,14 @@ No scraping. No browser. Just the API.
34
34
 
35
35
  ## How It Works
36
36
 
37
- 1. **Capture** — Launch a Playwright browser, visit a site, browse normally. ApiTap intercepts all network traffic via CDP.
37
+ 1. **Capture** — Launch a Playwright browser, visit a site, browse normally. ApiTap intercepts all network traffic via CDP. Or use `apitap attach` to capture from your already-running Chrome.
38
38
  2. **Filter** — Scoring engine separates signal from noise. Analytics, tracking pixels, and framework internals are filtered out. Only real API endpoints survive.
39
- 3. **Generate** — Captured endpoints are grouped by domain, URLs are parameterized (`/users/123` → `/users/:id`), and a JSON skill file is written to `~/.apitap/skills/`.
39
+ 3. **Generate** — Captured endpoints are grouped by domain, URLs are parameterized (`/users/123` → `/users/:id` with context-aware semantic names), and a JSON skill file is written to `~/.apitap/skills/`.
40
40
  4. **Replay** — Read the skill file, substitute parameters, call the API with `fetch()`. Zero dependencies in the replay path.
41
41
 
42
42
  ```
43
- Capture: Browser → Playwright listener → Filter → Skill Generator → skill.json
43
+ Capture: Browser → Playwright/CDP listener → Filter → Skill Generator → skill.json
44
+ Attach: Running Chrome → CDP attach → Filter → Skill Generator → skill.json
44
45
  Replay: Agent → Replay Engine (skill.json) → fetch() → API → JSON response
45
46
  ```
46
47
 
@@ -84,6 +85,22 @@ apitap capture https://polymarket.com --duration 30
84
85
 
85
86
  ApiTap opens a browser window. Browse the site normally — click around, scroll, search. Every API call is captured. Press Ctrl+C when done.
86
87
 
88
+ ### Attach to a running Chrome
89
+
90
+ ```bash
91
+ # Enable remote debugging in Chrome: Settings → Remote debugging → toggle on
92
+
93
+ # Attach to your signed-in Chrome — captures all tabs
94
+ apitap attach --port 9222
95
+
96
+ # Filter to specific domains
97
+ apitap attach --port 9222 --domain *.github.com
98
+
99
+ # Ctrl+C to stop — generates signed skill files for each captured domain
100
+ ```
101
+
102
+ No separate browser, no re-login. Captures from your real Chrome sessions with all your cookies and auth tokens.
103
+
87
104
  ### List and explore captured APIs
88
105
 
89
106
  ```bash
@@ -327,7 +344,7 @@ For one-off captures without the passive index:
327
344
  2. Browse the site — extension records API traffic
328
345
  3. Click **Stop** → skill file auto-saves to `~/.apitap/skills/`
329
346
 
330
- The popup shows CLI connection status and live capture stats. Auth tokens are automatically stored to `~/.apitap/auth.enc` with `[stored]` placeholders in the exported skill files.
347
+ The popup shows CLI connection status and live capture stats. Auth tokens are encrypted with AES-256-GCM in session storage and automatically persisted to `~/.apitap/auth.enc` via the native host, with `[stored]` placeholders in the exported skill files.
331
348
 
332
349
  > **Note:** Chrome Web Store submission coming soon. For now, load as an unpacked extension in Developer mode.
333
350
 
@@ -360,7 +377,7 @@ Skill files are JSON documents stored at `~/.apitap/skills/<domain>.json`. They
360
377
 
361
378
  ```json
362
379
  {
363
- "version": "1.1",
380
+ "version": 2,
364
381
  "domain": "gamma-api.polymarket.com",
365
382
  "baseUrl": "https://gamma-api.polymarket.com",
366
383
  "endpoints": [
@@ -425,7 +442,7 @@ Endpoint replayed
425
442
  → Redirect check: if server redirects, validate new target before following
426
443
  ```
427
444
 
428
- **Blocked ranges:** `127.0.0.0/8`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `169.254.0.0/16` (cloud metadata), `0.0.0.0`, IPv6 equivalents (`::1`, `fe80::/10`, `fc00::/7`, `::ffff:` mapped addresses), `localhost`, `.local`, `.internal`, `file://`, `javascript:` schemes.
445
+ **Blocked ranges:** `127.0.0.0/8`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `169.254.0.0/16` (cloud metadata), `100.64.0.0/10` (CGNAT/Tailscale), `198.18.0.0/15` (benchmarking), `240.0.0.0/4` (reserved), `0.0.0.0`, IPv6 equivalents (`::1`, `fe80::/10`, `fc00::/7`, `::ffff:` mapped addresses), `localhost`, `.local`, `.internal`, `file://`, `javascript:` schemes. Alternative IP representations (decimal integer, octal, hex) are normalized before checking.
429
446
 
430
447
  This is especially relevant now that [MCP servers are being used as attack vectors in the wild](https://cloud.google.com/blog/topics/threat-intelligence/distillation-experimentation-integration-ai-adversarial-use) — Google's Threat Intelligence Group recently documented underground toolkits built on compromised MCP servers. ApiTap is designed to be safe even when processing untrusted inputs.
431
448
 
@@ -442,6 +459,7 @@ All commands support `--json` for machine-readable output.
442
459
  | `apitap read <url>` | Extract content without a browser |
443
460
  | `apitap discover <url>` | Detect APIs without launching a browser |
444
461
  | `apitap capture <url>` | Capture API traffic from a website |
462
+ | `apitap attach --port <port>` | Attach to running Chrome and capture API traffic |
445
463
  | `apitap list` | List available skill files |
446
464
  | `apitap show <domain>` | Show endpoints for a domain |
447
465
  | `apitap search <query>` | Search skill files by domain or endpoint |
@@ -452,6 +470,7 @@ All commands support `--json` for machine-readable output.
452
470
  | `apitap serve <domain>` | Serve a skill file as an MCP server |
453
471
  | `apitap inspect <url>` | Discover APIs without saving |
454
472
  | `apitap stats` | Show token savings report |
473
+ | `apitap index [domain]` | View passive index from Chrome extension |
455
474
  | `apitap audit` | Audit stored skill files and credentials |
456
475
  | `apitap forget <domain>` | Remove skill file and credentials for a domain |
457
476
  | `apitap --version` | Print version |
@@ -468,6 +487,7 @@ All commands support `--json` for machine-readable output.
468
487
  | `--attach` | Only attach to existing browser |
469
488
  | `--no-scrub` | Disable PII scrubbing |
470
489
  | `--no-verify` | Skip auto-verification of GET endpoints |
490
+ | `--domain <glob>` | Filter traffic by domain glob (attach mode, e.g. `*.github.com`) |
471
491
 
472
492
  ## Development
473
493
 
@@ -475,7 +495,7 @@ All commands support `--json` for machine-readable output.
475
495
  git clone https://github.com/n1byn1kt/apitap.git
476
496
  cd apitap
477
497
  npm install
478
- npm test # 1051 tests, Node built-in test runner
498
+ npm test # ~1195 tests, Node built-in test runner
479
499
  npm run typecheck # Type checking
480
500
  npm run build # Compile to dist/
481
501
  npx tsx src/cli.ts capture <url> # Run from source
@@ -236,7 +236,7 @@ async function doHandoff(authManager, options) {
236
236
  const cookieDomain = (c.domain || '').replace(/^\./, ''); // Remove leading dot
237
237
  return cookieDomain === domain ||
238
238
  cookieDomain.endsWith('.' + domain) ||
239
- domain.endsWith('.' + cookieDomain);
239
+ (domain.endsWith('.' + cookieDomain) && cookieDomain.includes('.'));
240
240
  });
241
241
  if (cookies.length === 0 && !authDetected) {
242
242
  return {
@@ -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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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Test if a hostname matches any pattern in a domain glob list.
3
+ * Empty list means "match all" (no filter).
4
+ *
5
+ * Glob rules:
6
+ * - "api.github.com" — exact match
7
+ * - "*.github.com" — matches any subdomain AND the bare domain
8
+ * (the *. prefix means "zero or more subdomains")
9
+ */
10
+ export declare function matchesDomainGlob(hostname: string, patterns: string[]): boolean;
11
+ /**
12
+ * Parse a comma-separated domain pattern string into a list.
13
+ */
14
+ export declare function parseDomainPatterns(input: string | undefined): string[];
15
+ /**
16
+ * Discover Chrome's browser-level WebSocket URL via the /json/version endpoint.
17
+ */
18
+ export declare function discoverBrowserWsUrl(port: number): Promise<{
19
+ wsUrl: string;
20
+ browser: string;
21
+ tabCount: number;
22
+ }>;
23
+ /**
24
+ * Minimal CDP session over a single WebSocket.
25
+ * Supports browser-level commands and session-multiplexed target commands
26
+ * (via the sessionId parameter on send/events, using flatten: true).
27
+ */
28
+ export declare class CDPSession {
29
+ private wsUrl;
30
+ private ws;
31
+ private nextId;
32
+ private callbacks;
33
+ private listeners;
34
+ constructor(wsUrl: string);
35
+ connect(): Promise<void>;
36
+ send(method: string, params?: Record<string, unknown>, sessionId?: string): Promise<Record<string, unknown>>;
37
+ on(event: string, handler: (params: Record<string, unknown>) => void): void;
38
+ close(): void;
39
+ }
40
+ export interface AttachOptions {
41
+ port: number;
42
+ domainPatterns: string[];
43
+ json: boolean;
44
+ onProgress?: (line: string) => void;
45
+ }
46
+ export interface AttachResult {
47
+ domains: Array<{
48
+ domain: string;
49
+ endpoints: number;
50
+ skillFile: string;
51
+ }>;
52
+ totalRequests: number;
53
+ filteredRequests: number;
54
+ duration: number;
55
+ }
56
+ /**
57
+ * Attach to a running Chrome instance via CDP, passively capture API traffic
58
+ * across all tabs, and generate signed skill files on SIGINT.
59
+ */
60
+ export declare function attach(options: AttachOptions): Promise<AttachResult>;
@@ -0,0 +1,422 @@
1
+ // src/capture/cdp-attach.ts
2
+ import http from 'node:http';
3
+ import { homedir } from 'node:os';
4
+ import { shouldCapture } from './filter.js';
5
+ import { SkillGenerator, deduplicateAuth } from '../skill/generator.js';
6
+ import { signSkillFile } from '../skill/signing.js';
7
+ import { writeSkillFile } from '../skill/store.js';
8
+ import { AuthManager, getMachineId } from '../auth/manager.js';
9
+ import { deriveSigningKey } from '../auth/crypto.js';
10
+ import { join } from 'node:path';
11
+ // ---- Domain glob matching ----
12
+ /**
13
+ * Test if a hostname matches any pattern in a domain glob list.
14
+ * Empty list means "match all" (no filter).
15
+ *
16
+ * Glob rules:
17
+ * - "api.github.com" — exact match
18
+ * - "*.github.com" — matches any subdomain AND the bare domain
19
+ * (the *. prefix means "zero or more subdomains")
20
+ */
21
+ export function matchesDomainGlob(hostname, patterns) {
22
+ if (patterns.length === 0)
23
+ return true;
24
+ for (const pattern of patterns) {
25
+ if (pattern.startsWith('*.')) {
26
+ const base = pattern.slice(2); // "github.com"
27
+ // Match bare domain or any subdomain
28
+ if (hostname === base || hostname.endsWith('.' + base)) {
29
+ return true;
30
+ }
31
+ }
32
+ else {
33
+ if (hostname === pattern)
34
+ return true;
35
+ }
36
+ }
37
+ return false;
38
+ }
39
+ /**
40
+ * Parse a comma-separated domain pattern string into a list.
41
+ */
42
+ export function parseDomainPatterns(input) {
43
+ if (!input || input.trim() === '')
44
+ return [];
45
+ return input.split(',').map(p => p.trim()).filter(p => p.length > 0);
46
+ }
47
+ // ---- CDP HTTP discovery ----
48
+ function cdpGet(url) {
49
+ return new Promise((resolve, reject) => {
50
+ http.get(url, (res) => {
51
+ let data = '';
52
+ res.on('data', (chunk) => data += chunk);
53
+ res.on('end', () => {
54
+ try {
55
+ resolve(JSON.parse(data));
56
+ }
57
+ catch {
58
+ reject(new Error(`Invalid JSON from ${url}`));
59
+ }
60
+ });
61
+ }).on('error', reject);
62
+ });
63
+ }
64
+ /**
65
+ * Discover Chrome's browser-level WebSocket URL via the /json/version endpoint.
66
+ */
67
+ export async function discoverBrowserWsUrl(port) {
68
+ const versionInfo = await cdpGet(`http://127.0.0.1:${port}/json/version`);
69
+ const targets = await cdpGet(`http://127.0.0.1:${port}/json/list`);
70
+ const tabCount = targets.filter(t => t.type === 'page').length;
71
+ return {
72
+ wsUrl: versionInfo.webSocketDebuggerUrl,
73
+ browser: versionInfo.Browser,
74
+ tabCount,
75
+ };
76
+ }
77
+ // ---- CDP WebSocket session ----
78
+ /**
79
+ * Minimal CDP session over a single WebSocket.
80
+ * Supports browser-level commands and session-multiplexed target commands
81
+ * (via the sessionId parameter on send/events, using flatten: true).
82
+ */
83
+ export class CDPSession {
84
+ wsUrl;
85
+ ws = null;
86
+ nextId = 1;
87
+ callbacks = new Map();
88
+ listeners = new Map();
89
+ constructor(wsUrl) {
90
+ this.wsUrl = wsUrl;
91
+ }
92
+ connect() {
93
+ return new Promise((resolve, reject) => {
94
+ this.ws = new WebSocket(this.wsUrl);
95
+ this.ws.onopen = () => resolve();
96
+ this.ws.onerror = (e) => reject(new Error(`CDP WebSocket error: ${e}`));
97
+ this.ws.onclose = () => {
98
+ // Reject all pending callbacks
99
+ for (const [, cb] of this.callbacks) {
100
+ clearTimeout(cb.timer);
101
+ cb.reject(new Error('CDP connection closed'));
102
+ }
103
+ this.callbacks.clear();
104
+ // Fire close listeners
105
+ for (const handler of this.listeners.get('close') ?? []) {
106
+ handler({});
107
+ }
108
+ };
109
+ this.ws.onmessage = (event) => {
110
+ const msg = JSON.parse(typeof event.data === 'string' ? event.data : String(event.data));
111
+ // Handle command responses
112
+ if (msg.id !== undefined && this.callbacks.has(msg.id)) {
113
+ const cb = this.callbacks.get(msg.id);
114
+ clearTimeout(cb.timer);
115
+ this.callbacks.delete(msg.id);
116
+ if (msg.error) {
117
+ const err = msg.error;
118
+ cb.reject(new Error(`CDP: ${err.message}`));
119
+ }
120
+ else {
121
+ cb.resolve(msg.result);
122
+ }
123
+ }
124
+ // Handle events
125
+ if (msg.method) {
126
+ const sessionId = msg.sessionId;
127
+ // Fire session-scoped handlers: "sessionId:Event.name"
128
+ if (sessionId) {
129
+ const scopedKey = `${sessionId}:${msg.method}`;
130
+ for (const handler of this.listeners.get(scopedKey) ?? []) {
131
+ handler(msg.params);
132
+ }
133
+ }
134
+ // Fire global handlers (non-session-scoped)
135
+ for (const handler of this.listeners.get(msg.method) ?? []) {
136
+ handler({
137
+ ...msg.params,
138
+ ...(sessionId ? { _sessionId: sessionId } : {}),
139
+ });
140
+ }
141
+ }
142
+ };
143
+ });
144
+ }
145
+ send(method, params = {}, sessionId) {
146
+ const id = this.nextId++;
147
+ return new Promise((resolve, reject) => {
148
+ const timer = setTimeout(() => {
149
+ this.callbacks.delete(id);
150
+ reject(new Error(`CDP timeout: ${method}`));
151
+ }, 15000);
152
+ this.callbacks.set(id, {
153
+ resolve: resolve,
154
+ reject,
155
+ timer,
156
+ });
157
+ const msg = { id, method, params };
158
+ if (sessionId)
159
+ msg.sessionId = sessionId;
160
+ this.ws.send(JSON.stringify(msg));
161
+ });
162
+ }
163
+ on(event, handler) {
164
+ if (!this.listeners.has(event))
165
+ this.listeners.set(event, []);
166
+ this.listeners.get(event).push(handler);
167
+ }
168
+ close() {
169
+ if (this.ws) {
170
+ this.ws.close();
171
+ this.ws = null;
172
+ }
173
+ }
174
+ }
175
+ /**
176
+ * Attach to a running Chrome instance via CDP, passively capture API traffic
177
+ * across all tabs, and generate signed skill files on SIGINT.
178
+ */
179
+ export async function attach(options) {
180
+ const { port, domainPatterns, json } = options;
181
+ const log = (msg) => {
182
+ if (!json)
183
+ process.stderr.write(msg + '\n');
184
+ options.onProgress?.(msg);
185
+ };
186
+ // SIGINT state — registered before any connection attempt (spec requirement)
187
+ let stopping = false;
188
+ // Phase 0: Discover browser
189
+ let browserInfo;
190
+ try {
191
+ browserInfo = await discoverBrowserWsUrl(port);
192
+ }
193
+ catch {
194
+ log(`[attach] Cannot connect to Chrome on :${port}`);
195
+ log('');
196
+ log('To enable remote debugging, relaunch Chrome with:');
197
+ log(` google-chrome --remote-debugging-port=${port}`);
198
+ log('');
199
+ log('Or on macOS:');
200
+ log(` /Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome --remote-debugging-port=${port}`);
201
+ process.exit(1);
202
+ }
203
+ log(`[attach] Connected to ${browserInfo.browser} on :${port} (${browserInfo.tabCount} tabs)`);
204
+ if (domainPatterns.length > 0) {
205
+ log(`[attach] Watching domains: ${domainPatterns.join(', ')}`);
206
+ }
207
+ else {
208
+ log('[attach] Watching all domains');
209
+ }
210
+ // Phase 1: Connect browser-level CDP session
211
+ const browser = new CDPSession(browserInfo.wsUrl);
212
+ await browser.connect();
213
+ // Capture state
214
+ const generators = new Map();
215
+ const requests = new Map();
216
+ const responses = new Map();
217
+ let totalRequests = 0;
218
+ let filteredRequests = 0;
219
+ const startTime = Date.now();
220
+ const activeSessions = new Set();
221
+ const loggedSkippedDomains = new Set();
222
+ function enableNetworkForSession(sessionId) {
223
+ if (activeSessions.has(sessionId))
224
+ return;
225
+ activeSessions.add(sessionId);
226
+ // Prefix requestIds with sessionId to avoid collisions across tabs
227
+ const prefix = sessionId.slice(0, 8);
228
+ browser.on(`${sessionId}:Network.requestWillBeSent`, (params) => {
229
+ // Evict oldest entries if Maps grow too large (memory safety)
230
+ if (requests.size > 10000) {
231
+ const keys = [...requests.keys()].slice(0, 1000);
232
+ for (const k of keys) {
233
+ requests.delete(k);
234
+ responses.delete(k);
235
+ }
236
+ }
237
+ const key = `${prefix}:${params.requestId}`;
238
+ const request = params.request;
239
+ requests.set(key, {
240
+ url: request.url,
241
+ method: request.method,
242
+ headers: request.headers,
243
+ postData: request.postData,
244
+ });
245
+ });
246
+ browser.on(`${sessionId}:Network.responseReceived`, (params) => {
247
+ const key = `${prefix}:${params.requestId}`;
248
+ const response = params.response;
249
+ responses.set(key, {
250
+ status: response.status,
251
+ headers: response.headers,
252
+ mimeType: response.mimeType,
253
+ });
254
+ });
255
+ browser.on(`${sessionId}:Network.loadingFinished`, (params) => {
256
+ const key = `${prefix}:${params.requestId}`;
257
+ const req = requests.get(key);
258
+ const resp = responses.get(key);
259
+ if (!req || !resp)
260
+ return;
261
+ totalRequests++;
262
+ // Get response body immediately (before Chrome evicts it from buffer).
263
+ // This MUST be called synchronously in the handler — deferring risks
264
+ // "No resource with given identifier found" on high-traffic tabs.
265
+ browser.send('Network.getResponseBody', { requestId: params.requestId }, sessionId).then((result) => {
266
+ processExchange(key, req, resp, result.body ?? '', log);
267
+ }).catch(() => {
268
+ // Body evicted or unavailable — still process exchange without body
269
+ processExchange(key, req, resp, '', log);
270
+ });
271
+ });
272
+ // Enable network capture for this session (fire-and-forget)
273
+ browser.send('Network.enable', {}, sessionId).catch(() => {
274
+ // Session may have been destroyed
275
+ });
276
+ }
277
+ function processExchange(key, req, resp, body, logFn) {
278
+ // Apply shouldCapture filter
279
+ if (!shouldCapture({ url: req.url, status: resp.status, contentType: resp.mimeType })) {
280
+ filteredRequests++;
281
+ if (req.url.startsWith('chrome-extension://')) {
282
+ logFn(` [skip] ${req.url.slice(0, 50)}... (extension)`);
283
+ }
284
+ return;
285
+ }
286
+ // Apply domain glob filter
287
+ let hostname;
288
+ try {
289
+ hostname = new URL(req.url).hostname;
290
+ }
291
+ catch {
292
+ return;
293
+ }
294
+ if (!matchesDomainGlob(hostname, domainPatterns)) {
295
+ filteredRequests++;
296
+ if (!loggedSkippedDomains.has(hostname)) {
297
+ loggedSkippedDomains.add(hostname);
298
+ logFn(` [skip] ${hostname} (not in domain filter)`);
299
+ }
300
+ return;
301
+ }
302
+ // Get or create generator for this domain
303
+ if (!generators.has(hostname)) {
304
+ generators.set(hostname, new SkillGenerator());
305
+ }
306
+ const gen = generators.get(hostname);
307
+ const exchange = {
308
+ request: {
309
+ url: req.url,
310
+ method: req.method,
311
+ headers: req.headers,
312
+ postData: req.postData,
313
+ },
314
+ response: {
315
+ status: resp.status,
316
+ headers: resp.headers,
317
+ body,
318
+ contentType: resp.mimeType,
319
+ },
320
+ timestamp: new Date().toISOString(),
321
+ };
322
+ const endpoint = gen.addExchange(exchange);
323
+ if (endpoint) {
324
+ logFn(` [api] ${req.method} ${resp.status} ${hostname} ${endpoint.path}`);
325
+ }
326
+ // Clean up to avoid memory growth
327
+ requests.delete(key);
328
+ responses.delete(key);
329
+ }
330
+ // Phase 2: Attach to all existing page targets
331
+ const { targetInfos } = await browser.send('Target.getTargets');
332
+ for (const target of targetInfos) {
333
+ if (target.type === 'page') {
334
+ try {
335
+ const result = await browser.send('Target.attachToTarget', {
336
+ targetId: target.targetId,
337
+ flatten: true,
338
+ });
339
+ enableNetworkForSession(result.sessionId);
340
+ }
341
+ catch {
342
+ // Target may have navigated away
343
+ }
344
+ }
345
+ }
346
+ // Phase 3: Auto-attach to future targets (new tabs, popups, OAuth redirects).
347
+ // flatten: true is critical — uses session-based CDP multiplexing instead
348
+ // of legacy nested WebSocket connections.
349
+ browser.on('Target.attachedToTarget', (params) => {
350
+ const targetInfo = params.targetInfo;
351
+ if (targetInfo?.type === 'page') {
352
+ enableNetworkForSession(params.sessionId);
353
+ }
354
+ });
355
+ await browser.send('Target.setAutoAttach', {
356
+ autoAttach: true,
357
+ waitForDebuggerOnStart: false,
358
+ flatten: true,
359
+ });
360
+ // Phase 4: Wait for SIGINT or browser disconnect
361
+ const result = await new Promise((resolve) => {
362
+ const shutdown = async () => {
363
+ if (stopping) {
364
+ // Second SIGINT — force exit immediately
365
+ process.exit(1);
366
+ }
367
+ stopping = true;
368
+ log('');
369
+ const duration = Math.round((Date.now() - startTime) / 1000);
370
+ if (generators.size === 0) {
371
+ log('[attach] Nothing captured');
372
+ browser.close();
373
+ resolve({ domains: [], totalRequests, filteredRequests, duration });
374
+ return;
375
+ }
376
+ log('[attach] Generating skill files...');
377
+ const machineId = await getMachineId();
378
+ const signingKey = deriveSigningKey(machineId);
379
+ const apitapDir = process.env.APITAP_DIR || join(homedir(), '.apitap');
380
+ const authManager = new AuthManager(apitapDir, machineId);
381
+ const domains = [];
382
+ for (const [domain, gen] of generators) {
383
+ let skill = gen.toSkillFile(domain);
384
+ if (skill.endpoints.length === 0)
385
+ continue;
386
+ // Store extracted auth credentials
387
+ const auth = deduplicateAuth(gen.getExtractedAuth());
388
+ if (auth) {
389
+ await authManager.store(domain, auth);
390
+ }
391
+ // Store OAuth credentials if detected
392
+ const oauthConfig = gen.getOAuthConfig();
393
+ if (oauthConfig) {
394
+ const clientSecret = gen.getOAuthClientSecret();
395
+ const refreshToken = gen.getOAuthRefreshToken();
396
+ if (clientSecret || refreshToken) {
397
+ await authManager.storeOAuthCredentials(domain, {
398
+ ...(clientSecret ? { clientSecret } : {}),
399
+ ...(refreshToken ? { refreshToken } : {}),
400
+ });
401
+ }
402
+ }
403
+ skill = signSkillFile(skill, signingKey);
404
+ const skillPath = await writeSkillFile(skill);
405
+ const displayPath = skillPath.replace(homedir(), '~');
406
+ const count = skill.endpoints.length;
407
+ log(` ${domain} — ${count} endpoint${count === 1 ? '' : 's'} → ${displayPath}`);
408
+ domains.push({ domain, endpoints: count, skillFile: displayPath });
409
+ }
410
+ browser.close();
411
+ resolve({ domains, totalRequests, filteredRequests, duration });
412
+ };
413
+ process.on('SIGINT', shutdown);
414
+ // Handle browser disconnect (user closed Chrome)
415
+ browser.on('close', () => {
416
+ if (!stopping)
417
+ shutdown();
418
+ });
419
+ });
420
+ return result;
421
+ }
422
+ //# sourceMappingURL=cdp-attach.js.map