@crouton-kit/capture 1.3.7 → 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 (141) hide show
  1. package/bin/capture +32786 -9989
  2. package/package.json +9 -3
  3. package/src/capture.ts +86 -163
  4. package/src/cdp/a11y.ts +113 -14
  5. package/src/cdp/args.ts +300 -116
  6. package/src/cdp/bridge/protocol.ts +187 -1
  7. package/src/cdp/bridge/server.ts +211 -84
  8. package/src/cdp/bridge/spawn.ts +110 -1
  9. package/src/cdp/client.ts +13 -3
  10. package/src/cdp/commands/bridge-serve.ts +35 -4
  11. package/src/cdp/commands/cdp.ts +266 -69
  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 +87 -0
  15. package/src/cdp/commands/measure/check.ts +109 -0
  16. package/src/cdp/commands/measure/diff.ts +120 -0
  17. package/src/cdp/commands/measure/explain.ts +133 -0
  18. package/src/cdp/commands/measure/index.ts +106 -0
  19. package/src/cdp/commands/measure/map-ax.ts +52 -0
  20. package/src/cdp/commands/measure/map-focus.ts +52 -0
  21. package/src/cdp/commands/measure/map-layers.ts +59 -0
  22. package/src/cdp/commands/measure/map-scroll.ts +94 -0
  23. package/src/cdp/commands/measure/snap.ts +416 -0
  24. package/src/cdp/commands/measure/sweep.ts +227 -0
  25. package/src/cdp/commands/motion/index.ts +61 -0
  26. package/src/cdp/commands/motion/jank.ts +132 -0
  27. package/src/cdp/commands/motion/mask.ts +92 -0
  28. package/src/cdp/commands/motion/rec.ts +534 -0
  29. package/src/cdp/commands/motion/response.ts +76 -0
  30. package/src/cdp/commands/motion/timeline.ts +152 -0
  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/coordinates.ts +158 -0
  46. package/src/cdp/detect.ts +42 -13
  47. package/src/cdp/dispatch.ts +76 -26
  48. package/src/cdp/domains.ts +75 -0
  49. package/src/cdp/har-recorder.ts +648 -115
  50. package/src/cdp/leaf-grammar.ts +99 -0
  51. package/src/cdp/measure/census.ts +205 -0
  52. package/src/cdp/measure/check.ts +318 -0
  53. package/src/cdp/measure/collectors/animation.ts +385 -0
  54. package/src/cdp/measure/collectors/ax.ts +278 -0
  55. package/src/cdp/measure/collectors/focus.ts +1041 -0
  56. package/src/cdp/measure/collectors/forms.ts +905 -0
  57. package/src/cdp/measure/collectors/geometry.ts +1038 -0
  58. package/src/cdp/measure/collectors/hittest.ts +835 -0
  59. package/src/cdp/measure/collectors/layers.ts +697 -0
  60. package/src/cdp/measure/collectors/media.ts +522 -0
  61. package/src/cdp/measure/collectors/pixels.ts +1584 -0
  62. package/src/cdp/measure/collectors/queries.ts +464 -0
  63. package/src/cdp/measure/collectors/scroll.ts +599 -0
  64. package/src/cdp/measure/collectors/states.ts +992 -0
  65. package/src/cdp/measure/collectors/style-provenance.ts +643 -0
  66. package/src/cdp/measure/collectors/styles.ts +355 -0
  67. package/src/cdp/measure/collectors/text.ts +713 -0
  68. package/src/cdp/measure/diff.ts +470 -0
  69. package/src/cdp/measure/explain.ts +498 -0
  70. package/src/cdp/measure/map-ax.ts +633 -0
  71. package/src/cdp/measure/map-focus.ts +188 -0
  72. package/src/cdp/measure/map-layers.ts +177 -0
  73. package/src/cdp/measure/map-scroll.ts +317 -0
  74. package/src/cdp/measure/redaction.ts +51 -0
  75. package/src/cdp/measure/settle.ts +1051 -0
  76. package/src/cdp/measure/snapshot.ts +390 -0
  77. package/src/cdp/measure/sweep.ts +330 -0
  78. package/src/cdp/measure/types.ts +220 -0
  79. package/src/cdp/measure/v2/collectors.ts +19 -0
  80. package/src/cdp/measure/v2/orchestrator.ts +46 -0
  81. package/src/cdp/measure/v2/snap-selection.ts +33 -0
  82. package/src/cdp/measure/v2/target-lock.ts +15 -0
  83. package/src/cdp/measure/v2/target.ts +16 -0
  84. package/src/cdp/motion/jank.ts +433 -0
  85. package/src/cdp/motion/mask.ts +421 -0
  86. package/src/cdp/motion/recorder.ts +764 -0
  87. package/src/cdp/motion/response.ts +356 -0
  88. package/src/cdp/motion/timeline.ts +215 -0
  89. package/src/cdp/record.ts +5 -212
  90. package/src/cdp/recorder-bridge.ts +1894 -0
  91. package/src/cdp/recorder-client.ts +326 -0
  92. package/src/cdp/scope-lock.ts +73 -0
  93. package/src/cdp/screenshot.ts +199 -66
  94. package/src/cdp/source-map.ts +309 -0
  95. package/src/cdp/targets.ts +21 -1
  96. package/src/cdp/timing.ts +87 -0
  97. package/src/cdp/types.ts +87 -6
  98. package/src/cdp/viewport.ts +21 -0
  99. package/src/cdp.ts +12 -58
  100. package/src/command-help.ts +29 -0
  101. package/src/command-resolution.ts +22 -0
  102. package/src/command-walker.ts +35 -0
  103. package/src/contracts/a11y.ts +33 -0
  104. package/src/contracts/cursor.ts +35 -0
  105. package/src/contracts/index.ts +15 -0
  106. package/src/contracts/motion.ts +19 -0
  107. package/src/contracts/neutral.ts +56 -0
  108. package/src/contracts/primitives.ts +205 -0
  109. package/src/contracts/release.ts +17 -0
  110. package/src/contracts/results.ts +208 -0
  111. package/src/contracts/routes.ts +140 -0
  112. package/src/contracts/snapshot.ts +92 -0
  113. package/src/cursor/index.ts +13 -0
  114. package/src/cursor/service.ts +310 -0
  115. package/src/errors.ts +71 -0
  116. package/src/har-manager.ts +992 -41
  117. package/src/interact.ts +410 -98
  118. package/src/output/artifact-lifecycle.ts +371 -0
  119. package/src/output/artifact.ts +526 -0
  120. package/src/output/diff.ts +111 -0
  121. package/src/output/exact-raw.ts +114 -0
  122. package/src/output/render.ts +987 -0
  123. package/src/output/selector.ts +185 -0
  124. package/src/output/structured.ts +211 -0
  125. package/src/registry.ts +208 -0
  126. package/src/session/artifacts.ts +481 -0
  127. package/src/session/commands.ts +1237 -368
  128. package/src/session/coordinator.ts +251 -0
  129. package/src/session/har-filter.ts +57 -0
  130. package/src/session/log-tailer.ts +653 -0
  131. package/src/session-context.ts +302 -34
  132. package/src/vault/bundle.ts +32 -17
  133. package/src/cdp/commands/exec.ts +0 -105
  134. package/src/cdp/commands/har.ts +0 -128
  135. package/src/cdp/commands/tabs.ts +0 -183
  136. package/src/cdp/commands/traffic.ts +0 -121
  137. package/src/cdp/commands/ui.ts +0 -172
  138. package/src/cdp/execute.ts +0 -113
  139. package/src/cdp/har-output.ts +0 -47
  140. package/src/cdp/usage.ts +0 -77
  141. 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,77 +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
-
26
- Options:
27
- --port <port> Override CDP port
28
- --target <tabId> Target tab by exact ID (preferred, parallel-safe)
29
- CDP_PORT / CDP_TARGET Default port + tab when set by orchestrators
30
- --new Force new tab (open)
31
- --record Enable HAR recording (exec)
32
- --har <id> Append traffic to a HAR recording
33
- --har-out <path> HAR output path
34
- --file <path> Read JS from file (exec)
35
- --duration <secs> Recording duration (record, default: 10)
36
- --settle <ms> Settle time override (navigate, click, type)
37
- --filter-url <pat> Filter HAR entries by URL substring/regex (har read)
38
- --filter-status <s> Filter HAR by status: code, prefix (4), or range (400-499)
39
- --filter-method <m> Filter HAR by HTTP method (har read)
40
- --limit <N> Return only first N matching HAR entries (har read)
41
- --browser Target the browser-level connection (cdp)
42
- --params '<json>' JSON params for the method (cdp)
43
- --wait-event <name> Wait for a CDP event and return it (cdp)
44
- --timeout <ms> Wait timeout, default 10000 (cdp)
45
- --out <path> Output path (screenshot)
46
- --viewport <preset> Viewport preset: desktop-wide|desktop|tablet|mobile (default: desktop)
47
- --height <px> Override viewport height (screenshot)
48
- --full-page Capture entire scrollable page (screenshot)
49
- --json JSON output (a11y)
50
- --interactive Interactive elements only (a11y)
51
- --role <role> ARIA role filter (click)
52
- --into "field" Target field by name (type)
53
- --no-screenshot Skip auto-screenshot (click, type)
54
-
55
- Console output (errors, warnings) is always captured and printed to stderr.
56
-
57
- Examples:
58
- capture detect
59
- capture list
60
- capture open "https://app.example.com" --new
61
- capture exec "document.title" --target <id>
62
- capture exec "return document.title" --target <id>
63
- capture exec "const r = await fetch('/api/data'); return await r.json()" --target <id> --record
64
- capture exec --file /tmp/scrape.js --target <id>
65
- capture screenshot --target <id> --out /tmp/shot.png
66
- capture a11y --target <id> --interactive
67
- capture record --target <id> --duration 15
68
- capture navigate "https://app.example.com/dashboard"
69
- capture har create
70
- capture exec "document.querySelector('form').submit()" --target <id> --har <id>
71
- capture har read <id>
72
- capture lib search "search emails"
73
- capture lib read gmail searchEmails
74
- capture exec "import {searchEmails} from 'libs/gmail'; const ctx = await getContext(); return await searchEmails({ ...ctx, query: 'invoice' })"
75
- capture cdp Browser.grantPermissions --browser --params '{"origin":"http://localhost:3000","permissions":["notifications"]}'
76
- capture cdp --help Raw CDP escape hatch (Browser.*, ServiceWorker.*, ...) + how session --hold keeps grants alive
77
- `;
@@ -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
- }