@crouton-kit/capture 1.3.8 → 1.3.9

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 (136) hide show
  1. package/bin/capture +29841 -8539
  2. package/package.json +6 -3
  3. package/src/capture.ts +86 -173
  4. package/src/cdp/a11y.ts +113 -14
  5. package/src/cdp/args.ts +300 -205
  6. package/src/cdp/bridge/protocol.ts +93 -6
  7. package/src/cdp/bridge/server.ts +118 -53
  8. package/src/cdp/bridge/spawn.ts +53 -6
  9. package/src/cdp/client.ts +13 -3
  10. package/src/cdp/commands/bridge-serve.ts +20 -14
  11. package/src/cdp/commands/cdp.ts +259 -90
  12. package/src/cdp/commands/gate-guard.ts +43 -0
  13. package/src/cdp/commands/lib.ts +339 -213
  14. package/src/cdp/commands/measure/census.ts +76 -20
  15. package/src/cdp/commands/measure/check.ts +100 -26
  16. package/src/cdp/commands/measure/diff.ts +109 -21
  17. package/src/cdp/commands/measure/explain.ts +121 -19
  18. package/src/cdp/commands/measure/index.ts +31 -39
  19. package/src/cdp/commands/measure/map-ax.ts +52 -0
  20. package/src/cdp/commands/measure/map-focus.ts +41 -13
  21. package/src/cdp/commands/measure/map-layers.ts +49 -15
  22. package/src/cdp/commands/measure/map-scroll.ts +85 -15
  23. package/src/cdp/commands/measure/snap.ts +405 -25
  24. package/src/cdp/commands/measure/sweep.ts +217 -20
  25. package/src/cdp/commands/motion/index.ts +18 -17
  26. package/src/cdp/commands/motion/jank.ts +119 -9
  27. package/src/cdp/commands/motion/mask.ts +81 -12
  28. package/src/cdp/commands/motion/rec.ts +520 -19
  29. package/src/cdp/commands/motion/response.ts +65 -15
  30. package/src/cdp/commands/motion/timeline.ts +139 -14
  31. package/src/cdp/commands/page/click.ts +194 -0
  32. package/src/cdp/commands/page/elements.ts +154 -0
  33. package/src/cdp/commands/page/exec.ts +317 -0
  34. package/src/cdp/commands/page/index.ts +72 -0
  35. package/src/cdp/commands/page/navigate.ts +330 -0
  36. package/src/cdp/commands/page/scroll.ts +107 -0
  37. package/src/cdp/commands/page/shot.ts +208 -0
  38. package/src/cdp/commands/page/type.ts +104 -0
  39. package/src/cdp/commands/tab/index.ts +59 -0
  40. package/src/cdp/commands/tab/list.ts +167 -0
  41. package/src/cdp/commands/tab/network.ts +162 -0
  42. package/src/cdp/commands/tab/open.ts +90 -0
  43. package/src/cdp/commands/tab/reset.ts +160 -0
  44. package/src/cdp/connection.ts +368 -37
  45. package/src/cdp/detect.ts +42 -13
  46. package/src/cdp/dispatch.ts +74 -28
  47. package/src/cdp/har-recorder.ts +648 -115
  48. package/src/cdp/leaf-grammar.ts +99 -0
  49. package/src/cdp/measure/census.ts +205 -0
  50. package/src/cdp/measure/check.ts +318 -0
  51. package/src/cdp/measure/collectors/animation.ts +385 -0
  52. package/src/cdp/measure/collectors/ax.ts +278 -0
  53. package/src/cdp/measure/collectors/focus.ts +1041 -0
  54. package/src/cdp/measure/collectors/forms.ts +905 -0
  55. package/src/cdp/measure/collectors/geometry.ts +1038 -0
  56. package/src/cdp/measure/collectors/hittest.ts +835 -0
  57. package/src/cdp/measure/collectors/layers.ts +697 -0
  58. package/src/cdp/measure/collectors/media.ts +522 -0
  59. package/src/cdp/measure/collectors/pixels.ts +1584 -0
  60. package/src/cdp/measure/collectors/queries.ts +464 -0
  61. package/src/cdp/measure/collectors/scroll.ts +599 -0
  62. package/src/cdp/measure/collectors/states.ts +992 -0
  63. package/src/cdp/measure/collectors/style-provenance.ts +643 -0
  64. package/src/cdp/measure/collectors/styles.ts +355 -0
  65. package/src/cdp/measure/collectors/text.ts +713 -0
  66. package/src/cdp/measure/diff.ts +470 -0
  67. package/src/cdp/measure/explain.ts +498 -0
  68. package/src/cdp/measure/map-ax.ts +633 -0
  69. package/src/cdp/measure/map-focus.ts +188 -0
  70. package/src/cdp/measure/map-layers.ts +177 -0
  71. package/src/cdp/measure/map-scroll.ts +317 -0
  72. package/src/cdp/measure/redaction.ts +51 -0
  73. package/src/cdp/measure/settle.ts +1051 -0
  74. package/src/cdp/measure/snapshot.ts +390 -0
  75. package/src/cdp/measure/sweep.ts +330 -0
  76. package/src/cdp/measure/types.ts +220 -0
  77. package/src/cdp/measure/v2/collectors.ts +19 -0
  78. package/src/cdp/measure/v2/orchestrator.ts +46 -0
  79. package/src/cdp/measure/v2/snap-selection.ts +33 -0
  80. package/src/cdp/measure/v2/target-lock.ts +15 -0
  81. package/src/cdp/measure/v2/target.ts +16 -0
  82. package/src/cdp/motion/jank.ts +433 -0
  83. package/src/cdp/motion/mask.ts +421 -0
  84. package/src/cdp/motion/recorder.ts +764 -0
  85. package/src/cdp/motion/response.ts +356 -0
  86. package/src/cdp/motion/timeline.ts +215 -0
  87. package/src/cdp/record.ts +5 -212
  88. package/src/cdp/recorder-bridge.ts +1478 -105
  89. package/src/cdp/recorder-client.ts +326 -0
  90. package/src/cdp/scope-lock.ts +73 -0
  91. package/src/cdp/screenshot.ts +199 -66
  92. package/src/cdp/targets.ts +21 -1
  93. package/src/cdp/timing.ts +15 -10
  94. package/src/cdp/types.ts +22 -7
  95. package/src/cdp/viewport.ts +21 -0
  96. package/src/cdp.ts +12 -58
  97. package/src/command-help.ts +29 -0
  98. package/src/command-resolution.ts +22 -0
  99. package/src/command-walker.ts +35 -0
  100. package/src/contracts/a11y.ts +33 -0
  101. package/src/contracts/cursor.ts +35 -0
  102. package/src/contracts/index.ts +15 -0
  103. package/src/contracts/motion.ts +19 -0
  104. package/src/contracts/neutral.ts +56 -0
  105. package/src/contracts/primitives.ts +205 -0
  106. package/src/contracts/release.ts +17 -0
  107. package/src/contracts/results.ts +208 -0
  108. package/src/contracts/routes.ts +140 -0
  109. package/src/contracts/snapshot.ts +92 -0
  110. package/src/cursor/index.ts +13 -0
  111. package/src/cursor/service.ts +310 -0
  112. package/src/errors.ts +71 -0
  113. package/src/har-manager.ts +992 -41
  114. package/src/interact.ts +410 -98
  115. package/src/output/artifact-lifecycle.ts +371 -0
  116. package/src/output/artifact.ts +6 -0
  117. package/src/output/exact-raw.ts +114 -0
  118. package/src/output/render.ts +396 -2
  119. package/src/output/structured.ts +211 -0
  120. package/src/registry.ts +208 -0
  121. package/src/session/artifacts.ts +452 -200
  122. package/src/session/commands.ts +1162 -397
  123. package/src/session/coordinator.ts +251 -0
  124. package/src/session/har-filter.ts +57 -0
  125. package/src/session/log-tailer.ts +653 -0
  126. package/src/session-context.ts +279 -51
  127. package/src/vault/bundle.ts +32 -17
  128. package/src/cdp/commands/exec.ts +0 -105
  129. package/src/cdp/commands/har.ts +0 -128
  130. package/src/cdp/commands/tabs.ts +0 -183
  131. package/src/cdp/commands/traffic.ts +0 -121
  132. package/src/cdp/commands/ui.ts +0 -172
  133. package/src/cdp/execute.ts +0 -113
  134. package/src/cdp/har-output.ts +0 -47
  135. package/src/cdp/usage.ts +0 -79
  136. package/src/tab-session.ts +0 -91
@@ -1,113 +0,0 @@
1
- import { CDPClient } from './client.js';
2
- import { findTabByIdAcrossEndpoints } from './targets.js';
3
- import { buildExecExpression } from './exec-expression.js';
4
- import { ConsoleRecorder, type ConsoleEntry } from './console-recorder.js';
5
- import { HARRecorder } from './har-recorder.js';
6
- import { printConsoleSummary } from './console-recorder.js';
7
- import { writeHarAndPrintSummary } from './har-output.js';
8
- import { type HAREntry } from '../har-manager.js';
9
-
10
- export interface ExecuteOptions {
11
- port?: number;
12
- targetId?: string;
13
- record?: boolean;
14
- harOutPath?: string;
15
- timeoutMs?: number;
16
- }
17
-
18
- export interface ExecuteResult {
19
- success: boolean;
20
- value?: unknown;
21
- error?: string;
22
- har?: { log: { entries: HAREntry[] } };
23
- console: ConsoleEntry[];
24
- }
25
-
26
- export async function executeInBrowser(
27
- code: string,
28
- options: ExecuteOptions = {},
29
- ): Promise<ExecuteResult> {
30
- if (!options.targetId) {
31
- throw new Error('Use --target <tabId> to target a tab. Run "capture list" to see available tabs.');
32
- }
33
-
34
- const resolved = await findTabByIdAcrossEndpoints(options.targetId, options.port);
35
- const tab = resolved?.tab ?? null;
36
- if (!tab) {
37
- throw new Error(
38
- `No tab found for target "${options.targetId}". Run "capture list" to see available tabs.`,
39
- );
40
- }
41
-
42
- if (!tab.webSocketDebuggerUrl) {
43
- throw new Error('Tab has no WebSocket debugger URL');
44
- }
45
-
46
- const client = new CDPClient(tab.webSocketDebuggerUrl);
47
- await client.waitReady();
48
-
49
- // Emulate focus so network requests aren't deferred by the browser,
50
- // without actually bringing the tab to the foreground
51
- await client.send('Emulation.setFocusEmulationEnabled', { enabled: true });
52
-
53
- const consoleRecorder = new ConsoleRecorder(client);
54
- await consoleRecorder.start();
55
-
56
- let harRecorder: HARRecorder | undefined;
57
- if (options.record) {
58
- harRecorder = new HARRecorder(client);
59
- await harRecorder.start();
60
- }
61
-
62
- try {
63
- // Execute code
64
- const result = (await client.send(
65
- 'Runtime.evaluate',
66
- {
67
- expression: buildExecExpression(code),
68
- awaitPromise: true,
69
- returnByValue: true,
70
- },
71
- options.timeoutMs,
72
- )) as {
73
- result?: { value?: unknown };
74
- exceptionDetails?: { exception?: { description?: string } };
75
- };
76
-
77
- // Build HAR if recording
78
- let har: { log: { entries: HAREntry[] } } | undefined;
79
- if (harRecorder) {
80
- har = await harRecorder.finish();
81
- writeHarAndPrintSummary(har, options.harOutPath);
82
- }
83
-
84
- const consoleEntries = consoleRecorder.finish();
85
- printConsoleSummary(consoleEntries);
86
- client.close();
87
-
88
- if (result.exceptionDetails) {
89
- return {
90
- success: false,
91
- error:
92
- result.exceptionDetails.exception?.description ?? 'Unknown error',
93
- har,
94
- console: consoleEntries,
95
- };
96
- }
97
-
98
- return {
99
- success: true,
100
- value: result.result?.value,
101
- har,
102
- console: consoleEntries,
103
- };
104
- } catch (err) {
105
- const consoleEntries = consoleRecorder.finish();
106
- client.close();
107
- return {
108
- success: false,
109
- error: err instanceof Error ? err.message : String(err),
110
- console: consoleEntries,
111
- };
112
- }
113
- }
@@ -1,47 +0,0 @@
1
- import * as fs from 'fs';
2
- import { type HAREntry } from '../har-manager.js';
3
-
4
- export function writeHarAndPrintSummary(
5
- har: { log: { entries: HAREntry[] } },
6
- harOutPath?: string,
7
- ): string | undefined {
8
- if (har.log.entries.length === 0 && !harOutPath) return undefined;
9
-
10
- const harPath = harOutPath ?? `/tmp/capture-har-${Date.now()}.json`;
11
- try {
12
- fs.writeFileSync(harPath, JSON.stringify(har, null, 2));
13
- } catch (err) {
14
- // Fallback: strip response bodies and retry
15
- const stripped = {
16
- log: {
17
- ...har.log,
18
- entries: har.log.entries.map((e) => ({
19
- ...e,
20
- response: { ...e.response, content: { text: '[body stripped — too large to serialize]' } },
21
- })),
22
- },
23
- };
24
- fs.writeFileSync(harPath, JSON.stringify(stripped, null, 2));
25
- console.error(' WARNING: Response bodies stripped from HAR (too large to serialize)');
26
- }
27
-
28
- // Print summary to stderr
29
- const errors = har.log.entries.filter((e) => e.response.status >= 400);
30
- console.error(
31
- `\nHAR: ${har.log.entries.length} requests captured → ${harPath}`,
32
- );
33
- if (errors.length > 0) {
34
- console.error(` ${errors.length} failed:`);
35
- for (const entry of errors) {
36
- const method = entry.request.method.padEnd(6);
37
- const status = entry.response.status;
38
- const url =
39
- entry.request.url.length > 100
40
- ? entry.request.url.slice(0, 97) + '...'
41
- : entry.request.url;
42
- console.error(` ${method} ${status} ${url}`);
43
- }
44
- }
45
-
46
- return harPath;
47
- }
package/src/cdp/usage.ts DELETED
@@ -1,79 +0,0 @@
1
- export const CDP_USAGE = `CDP — browser automation via exec, a11y interactions, and screenshots.
2
-
3
- Commands:
4
- exec <code> Execute JavaScript in a browser tab (expressions, return, await)
5
- exec --file <path> Execute JS from file
6
- detect Detect CDP port (prioritizes default browser)
7
- list List all browser tabs
8
- open <url> Open URL in browser (returns tab ID)
9
- reset-tab <url> Abandon stuck tab, open fresh one (updates session)
10
- screenshot Capture screenshot
11
- click "name" Click element by accessible name
12
- type "text" Type text into focused element
13
- a11y Get accessibility tree
14
- record Passive HAR recording
15
- navigate <url> Navigate to URL and record HAR
16
- network <offline|online> Toggle network (simulate disconnect)
17
- har create Create a HAR recording (returns id)
18
- har read [id] Read accumulated HAR entries (id optional in active session)
19
- har delete <id> Delete a HAR recording
20
- lib list List available vault libs (dev checkout only)
21
- lib search "<q>" Fuzzy-search lib functions [--limit N]
22
- lib show <name> Lib + function summaries
23
- lib read <name> [fn…] Full input/output schemas (+ .ts source path)
24
- cdp <Domain.method> Send a raw CDP command capture doesn't wrap [--browser] [--params json] [--wait-event name]
25
- measure <leaf> Enriched snapshot substrate + read-only queries — see \`capture measure --help\`
26
- motion <leaf> Recorder lifecycle + read-only queries over a recording — see \`capture motion --help\`
27
-
28
- Options:
29
- --port <port> Override CDP port
30
- --target <tabId> Target tab by exact ID (preferred, parallel-safe)
31
- CDP_PORT / CDP_TARGET Default port + tab when set by orchestrators
32
- --new Force new tab (open)
33
- --record Enable HAR recording (exec)
34
- --har <id> Append traffic to a HAR recording
35
- --har-out <path> HAR output path
36
- --file <path> Read JS from file (exec)
37
- --duration <secs> Recording duration (record, default: 10)
38
- --settle <ms> Settle time override (navigate, click, type)
39
- --filter-url <pat> Filter HAR entries by URL substring/regex (har read)
40
- --filter-status <s> Filter HAR by status: code, prefix (4), or range (400-499)
41
- --filter-method <m> Filter HAR by HTTP method (har read)
42
- --limit <N> Return only first N matching HAR entries (har read)
43
- --browser Target the browser-level connection (cdp)
44
- --params '<json>' JSON params for the method (cdp)
45
- --wait-event <name> Wait for a CDP event and return it (cdp)
46
- --timeout <ms> Wait timeout, default 10000 (cdp)
47
- --out <path> Output path (screenshot)
48
- --viewport <preset> Viewport preset: desktop-wide|desktop|tablet|mobile (default: desktop)
49
- --height <px> Override viewport height (screenshot)
50
- --full-page Capture entire scrollable page (screenshot)
51
- --json JSON output (a11y)
52
- --interactive Interactive elements only (a11y)
53
- --role <role> ARIA role filter (click)
54
- --into "field" Target field by name (type)
55
- --no-screenshot Skip auto-screenshot (click, type)
56
-
57
- Console output (errors, warnings) is always captured and printed to stderr.
58
-
59
- Examples:
60
- capture detect
61
- capture list
62
- capture open "https://app.example.com" --new
63
- capture exec "document.title" --target <id>
64
- capture exec "return document.title" --target <id>
65
- capture exec "const r = await fetch('/api/data'); return await r.json()" --target <id> --record
66
- capture exec --file /tmp/scrape.js --target <id>
67
- capture screenshot --target <id> --out /tmp/shot.png
68
- capture a11y --target <id> --interactive
69
- capture record --target <id> --duration 15
70
- capture navigate "https://app.example.com/dashboard"
71
- capture har create
72
- capture exec "document.querySelector('form').submit()" --target <id> --har <id>
73
- capture har read <id>
74
- capture lib search "search emails"
75
- capture lib read gmail searchEmails
76
- capture exec "import {searchEmails} from 'libs/gmail'; const ctx = await getContext(); return await searchEmails({ ...ctx, query: 'invoice' })"
77
- capture cdp Browser.grantPermissions --browser --params '{"origin":"http://localhost:3000","permissions":["notifications"]}'
78
- capture cdp --help Raw CDP escape hatch (Browser.*, ServiceWorker.*, ...) + how session --hold keeps grants alive
79
- `;
@@ -1,91 +0,0 @@
1
- /**
2
- * TabSession — universal tab lifecycle abstraction for parallel-safe CDP usage.
3
- *
4
- * Manages: tab creation, HAR recording, environment injection, and cleanup.
5
- * Callers create a TabSession, pass its env() to downstream scripts, and close() when done.
6
- *
7
- * Usage:
8
- * const session = await TabSession.create({ url: 'https://app.hubspot.com' });
9
- * console.log(session.env()); // { CDP_TARGET: '...', CDP_HAR_ID: '...' }
10
- * await session.validate(); // throws if tab is gone
11
- * await session.close(); // closes tab + deletes HAR
12
- */
13
-
14
- import {
15
- navigateAndWait,
16
- findTabById,
17
- detectCdpPort,
18
- CDPClient,
19
- } from './cdp.js';
20
- import { createHarRecording, deleteHarRecording } from './har-manager.js';
21
-
22
- export interface TabSessionOptions {
23
- url: string;
24
- forceNew?: boolean; // Default true (parallel-safe)
25
- createHar?: boolean; // Default true
26
- cdpPort?: number; // Auto-detect if not provided
27
- }
28
-
29
- export interface TabSessionEnv {
30
- CDP_TARGET: string;
31
- CDP_HAR_ID?: string;
32
- }
33
-
34
- export class TabSession {
35
- readonly tabTarget: string;
36
- readonly harId: string | null;
37
- readonly cdpPort: number;
38
- private closed = false;
39
-
40
- private constructor(
41
- tabTarget: string,
42
- harId: string | null,
43
- cdpPort: number,
44
- ) {
45
- this.tabTarget = tabTarget;
46
- this.harId = harId;
47
- this.cdpPort = cdpPort;
48
- }
49
-
50
- static async create(options: TabSessionOptions): Promise<TabSession> {
51
- const port = options.cdpPort ?? (await detectCdpPort());
52
- const tab = await navigateAndWait(port, options.url, {
53
- forceNew: options.forceNew ?? true,
54
- });
55
- let harId: string | null = null;
56
- if (options.createHar !== false) {
57
- harId = createHarRecording().id;
58
- }
59
- return new TabSession(tab.id, harId, port);
60
- }
61
-
62
- async validate(): Promise<void> {
63
- const tab = await findTabById(this.cdpPort, this.tabTarget);
64
- if (!tab) throw new Error(`Tab ${this.tabTarget} no longer exists`);
65
- }
66
-
67
- env(): TabSessionEnv {
68
- const result: TabSessionEnv = { CDP_TARGET: this.tabTarget };
69
- if (this.harId) result.CDP_HAR_ID = this.harId;
70
- return result;
71
- }
72
-
73
- async close(): Promise<void> {
74
- if (this.closed) return;
75
- this.closed = true;
76
- try {
77
- const tab = await findTabById(this.cdpPort, this.tabTarget);
78
- if (tab?.webSocketDebuggerUrl) {
79
- const client = new CDPClient(tab.webSocketDebuggerUrl);
80
- await client.waitReady();
81
- await client.send('Runtime.evaluate', {
82
- expression: 'window.close()',
83
- });
84
- client.close();
85
- }
86
- } catch {
87
- /* best-effort */
88
- }
89
- if (this.harId) deleteHarRecording(this.harId);
90
- }
91
- }