browser-debugger-cli 0.12.0 → 0.14.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 (224) hide show
  1. package/.claude/skills/bdg/SKILL.md +100 -186
  2. package/README.md +5 -4
  3. package/dist/commands/cdp.d.ts +22 -1
  4. package/dist/commands/cdp.js +100 -43
  5. package/dist/commands/console.d.ts +12 -0
  6. package/dist/commands/console.js +67 -13
  7. package/dist/commands/dom/DomElementResolver.d.ts +3 -1
  8. package/dist/commands/dom/DomElementResolver.js +10 -3
  9. package/dist/commands/dom/a11y.d.ts +1 -1
  10. package/dist/commands/dom/a11y.js +23 -22
  11. package/dist/commands/dom/eval.d.ts +4 -2
  12. package/dist/commands/dom/eval.js +31 -7
  13. package/dist/commands/dom/form.js +10 -9
  14. package/dist/commands/dom/formInteraction.js +9 -8
  15. package/dist/commands/dom/get.js +32 -14
  16. package/dist/commands/dom/helpers/index.d.ts +1 -1
  17. package/dist/commands/dom/helpers/index.js +1 -1
  18. package/dist/commands/dom/helpers/query.d.ts +27 -3
  19. package/dist/commands/dom/helpers/query.js +152 -64
  20. package/dist/commands/dom/helpers/screenshot.js +13 -13
  21. package/dist/commands/dom/index.js +10 -3
  22. package/dist/commands/dom/query.d.ts +20 -2
  23. package/dist/commands/dom/query.js +39 -6
  24. package/dist/commands/dom/screenshot.js +3 -1
  25. package/dist/commands/dom/semanticUtils.d.ts +3 -2
  26. package/dist/commands/dom/semanticUtils.js +40 -9
  27. package/dist/commands/helpJson.d.ts +82 -19
  28. package/dist/commands/helpJson.js +112 -41
  29. package/dist/commands/helpTopic.d.ts +16 -1
  30. package/dist/commands/helpTopic.js +59 -1
  31. package/dist/commands/installSkill.d.ts +15 -5
  32. package/dist/commands/installSkill.js +86 -16
  33. package/dist/commands/network/list.js +65 -12
  34. package/dist/commands/optionBehaviors.d.ts +25 -2
  35. package/dist/commands/optionBehaviors.js +81 -46
  36. package/dist/commands/peek.js +3 -0
  37. package/dist/commands/shared/CommandRunner.js +13 -13
  38. package/dist/commands/shared/daemonErrorHandler.d.ts +5 -2
  39. package/dist/commands/shared/daemonErrorHandler.js +21 -10
  40. package/dist/commands/shared/dataFetcher.d.ts +14 -4
  41. package/dist/commands/shared/dataFetcher.js +20 -4
  42. package/dist/commands/shared/followMode.d.ts +9 -1
  43. package/dist/commands/shared/followMode.js +22 -4
  44. package/dist/commands/shared/handleValidationError.js +3 -3
  45. package/dist/commands/shared/optionTypes.d.ts +17 -3
  46. package/dist/commands/shared/outputFile.js +6 -1
  47. package/dist/commands/shared/startHelpers.js +3 -3
  48. package/dist/commands/start.d.ts +7 -5
  49. package/dist/commands/start.js +65 -21
  50. package/dist/commands/stop.d.ts +11 -0
  51. package/dist/commands/stop.js +24 -1
  52. package/dist/commands.js +1 -1
  53. package/dist/connection/cdp.d.ts +7 -0
  54. package/dist/connection/cdp.js +9 -0
  55. package/dist/connection/chromeIdentity.d.ts +8 -2
  56. package/dist/connection/chromeIdentity.js +85 -13
  57. package/dist/connection/launcher.js +3 -2
  58. package/dist/constants.d.ts +29 -1
  59. package/dist/constants.js +35 -1
  60. package/dist/daemon/SessionController.js +8 -1
  61. package/dist/daemon/launcher.d.ts +3 -2
  62. package/dist/daemon/launcher.js +47 -3
  63. package/dist/daemon/session/Session.d.ts +5 -1
  64. package/dist/daemon/session/Session.js +42 -3
  65. package/dist/daemon/session/TelemetryStore.d.ts +15 -1
  66. package/dist/daemon/session/TelemetryStore.js +19 -1
  67. package/dist/daemon/session/commandRegistry.js +52 -18
  68. package/dist/daemon/session/interactions.d.ts +2 -1
  69. package/dist/daemon/session/interactions.js +13 -1
  70. package/dist/daemon/session/matchedStylesReset.d.ts +26 -0
  71. package/dist/daemon/session/matchedStylesReset.js +46 -0
  72. package/dist/daemon/session/plugins.js +17 -2
  73. package/dist/daemon/session/teardown.js +1 -1
  74. package/dist/daemon/session/triggeredRequests.d.ts +0 -5
  75. package/dist/daemon/session/triggeredRequests.js +13 -7
  76. package/dist/daemon.js +2385 -1229
  77. package/dist/errors/messages.d.ts +62 -11
  78. package/dist/errors/messages.js +119 -22
  79. package/dist/index.js +14995 -9866
  80. package/dist/ipc/client.d.ts +18 -2
  81. package/dist/ipc/client.js +26 -5
  82. package/dist/ipc/protocol/auditTypes.d.ts +8 -2
  83. package/dist/ipc/protocol/commands.d.ts +16 -0
  84. package/dist/ipc/protocol/domTypes.d.ts +12 -0
  85. package/dist/ipc/protocol/inspectTypes.d.ts +7 -2
  86. package/dist/ipc/session/types.d.ts +7 -1
  87. package/dist/program.d.ts +14 -0
  88. package/dist/program.js +53 -0
  89. package/dist/runtime/dom/actionEffects.d.ts +5 -1
  90. package/dist/runtime/dom/actionEffects.js +26 -14
  91. package/dist/runtime/dom/audit.js +3 -2
  92. package/dist/runtime/dom/auditModel.js +6 -1
  93. package/dist/runtime/dom/auditScripts.d.ts +9 -3
  94. package/dist/runtime/dom/auditScripts.js +41 -5
  95. package/dist/runtime/dom/elementGeometry.d.ts +33 -3
  96. package/dist/runtime/dom/elementGeometry.js +44 -19
  97. package/dist/runtime/dom/elementInfo.d.ts +76 -18
  98. package/dist/runtime/dom/elementInfo.js +190 -40
  99. package/dist/runtime/dom/evalHelpers.d.ts +12 -2
  100. package/dist/runtime/dom/evalHelpers.js +67 -7
  101. package/dist/runtime/dom/formDiscovery.d.ts +6 -2
  102. package/dist/runtime/dom/formDiscovery.js +20 -3
  103. package/dist/runtime/dom/formFillHelpers/fill.js +7 -11
  104. package/dist/runtime/dom/formFillHelpers/pressKey.js +2 -2
  105. package/dist/runtime/dom/formFillHelpers/shared.d.ts +16 -10
  106. package/dist/runtime/dom/formFillHelpers/shared.js +19 -52
  107. package/dist/runtime/dom/formSubmitHelpers.js +4 -3
  108. package/dist/runtime/dom/frameLayout.js +1 -0
  109. package/dist/runtime/dom/frameScopedConnection.d.ts +7 -0
  110. package/dist/runtime/dom/frameScopedConnection.js +2 -2
  111. package/dist/runtime/dom/inspect.d.ts +17 -3
  112. package/dist/runtime/dom/inspect.js +45 -32
  113. package/dist/runtime/dom/inspectAllStyles.js +1 -0
  114. package/dist/runtime/dom/inspectHints.d.ts +1 -1
  115. package/dist/runtime/dom/inspectModel.d.ts +5 -4
  116. package/dist/runtime/dom/inspectModel.js +7 -3
  117. package/dist/runtime/dom/inspectPaintModel.d.ts +2 -0
  118. package/dist/runtime/dom/inspectPaintModel.js +3 -1
  119. package/dist/runtime/dom/inspectRules.d.ts +29 -3
  120. package/dist/runtime/dom/inspectRules.js +205 -11
  121. package/dist/runtime/dom/inspectScripts.d.ts +29 -2
  122. package/dist/runtime/dom/inspectScripts.js +49 -10
  123. package/dist/runtime/dom/layout.d.ts +0 -2
  124. package/dist/runtime/dom/layout.js +10 -9
  125. package/dist/runtime/dom/reactEventHelpers.d.ts +17 -4
  126. package/dist/runtime/dom/reactEventHelpers.js +71 -28
  127. package/dist/runtime/dom/targetNode.d.ts +27 -10
  128. package/dist/runtime/dom/targetNode.js +283 -16
  129. package/dist/runtime/dom/wait.js +2 -1
  130. package/dist/runtime/page/bdgWorld.d.ts +57 -0
  131. package/dist/runtime/page/bdgWorld.js +180 -0
  132. package/dist/runtime/page/replacedBuiltins.d.ts +28 -0
  133. package/dist/runtime/page/replacedBuiltins.js +136 -0
  134. package/dist/session/QueryCacheManager.d.ts +4 -1
  135. package/dist/session/QueryCacheManager.js +5 -2
  136. package/dist/session/chrome.d.ts +4 -1
  137. package/dist/session/chrome.js +7 -1
  138. package/dist/session/cleanup/staleSession.d.ts +21 -4
  139. package/dist/session/cleanup/staleSession.js +79 -9
  140. package/dist/session/cleanup/userCommands.d.ts +4 -1
  141. package/dist/session/cleanup/userCommands.js +10 -5
  142. package/dist/session/daemonSocket.d.ts +10 -0
  143. package/dist/session/daemonSocket.js +22 -0
  144. package/dist/session/lastSession.d.ts +6 -3
  145. package/dist/session/lastSession.js +11 -5
  146. package/dist/session/paths.d.ts +3 -1
  147. package/dist/session/paths.js +5 -5
  148. package/dist/session/portClaims.js +4 -3
  149. package/dist/session/sessionList.d.ts +13 -5
  150. package/dist/session/sessionList.js +31 -7
  151. package/dist/telemetry/a11y.d.ts +15 -1
  152. package/dist/telemetry/a11y.js +85 -2
  153. package/dist/telemetry/console.d.ts +2 -1
  154. package/dist/telemetry/console.js +30 -21
  155. package/dist/telemetry/har/builder.js +1 -1
  156. package/dist/telemetry/network.d.ts +13 -16
  157. package/dist/telemetry/network.js +30 -52
  158. package/dist/telemetry/networkRetention.d.ts +83 -0
  159. package/dist/telemetry/networkRetention.js +117 -0
  160. package/dist/telemetry/pageCrash.d.ts +26 -0
  161. package/dist/telemetry/pageCrash.js +53 -0
  162. package/dist/types.d.ts +42 -0
  163. package/dist/ui/OutputBuilder.d.ts +10 -0
  164. package/dist/ui/OutputBuilder.js +12 -0
  165. package/dist/ui/formatters/a11y.d.ts +5 -7
  166. package/dist/ui/formatters/a11y.js +7 -61
  167. package/dist/ui/formatters/audit.js +14 -5
  168. package/dist/ui/formatters/cdp.d.ts +138 -0
  169. package/dist/ui/formatters/cdp.js +131 -0
  170. package/dist/ui/formatters/console/chronological.js +7 -5
  171. package/dist/ui/formatters/console/follow.d.ts +5 -2
  172. package/dist/ui/formatters/console/follow.js +7 -4
  173. package/dist/ui/formatters/console/json.d.ts +4 -7
  174. package/dist/ui/formatters/console/json.js +16 -14
  175. package/dist/ui/formatters/console/shared.d.ts +47 -2
  176. package/dist/ui/formatters/console/shared.js +33 -0
  177. package/dist/ui/formatters/console/summarize.d.ts +9 -2
  178. package/dist/ui/formatters/console/summarize.js +57 -11
  179. package/dist/ui/formatters/console.d.ts +3 -2
  180. package/dist/ui/formatters/console.js +8 -10
  181. package/dist/ui/formatters/details.js +4 -2
  182. package/dist/ui/formatters/dom.d.ts +14 -5
  183. package/dist/ui/formatters/dom.js +30 -13
  184. package/dist/ui/formatters/helpFormatters.js +1 -1
  185. package/dist/ui/formatters/inspect.js +9 -3
  186. package/dist/ui/formatters/installSkill.d.ts +9 -1
  187. package/dist/ui/formatters/installSkill.js +32 -6
  188. package/dist/ui/formatters/layout.js +4 -2
  189. package/dist/ui/formatters/longValues.d.ts +14 -0
  190. package/dist/ui/formatters/longValues.js +23 -0
  191. package/dist/ui/formatters/networkList.d.ts +8 -2
  192. package/dist/ui/formatters/networkList.js +11 -3
  193. package/dist/ui/formatters/preview.d.ts +6 -1
  194. package/dist/ui/formatters/preview.js +67 -15
  195. package/dist/ui/formatters/sessions.d.ts +2 -2
  196. package/dist/ui/formatters/sessions.js +9 -2
  197. package/dist/ui/formatters/status.js +7 -0
  198. package/dist/ui/formatters/triggeredRequests.js +2 -1
  199. package/dist/ui/logging/logger.d.ts +1 -1
  200. package/dist/ui/messages/chrome.d.ts +20 -1
  201. package/dist/ui/messages/chrome.js +29 -3
  202. package/dist/ui/messages/commands.d.ts +153 -12
  203. package/dist/ui/messages/commands.js +198 -15
  204. package/dist/ui/messages/consoleMessages.d.ts +24 -0
  205. package/dist/ui/messages/consoleMessages.js +32 -0
  206. package/dist/ui/messages/networkMessages.d.ts +24 -0
  207. package/dist/ui/messages/networkMessages.js +45 -0
  208. package/dist/ui/messages/preview.d.ts +6 -0
  209. package/dist/ui/messages/preview.js +9 -1
  210. package/dist/ui/messages/session.d.ts +13 -2
  211. package/dist/ui/messages/session.js +22 -3
  212. package/dist/utils/directories.d.ts +34 -0
  213. package/dist/utils/directories.js +88 -0
  214. package/dist/utils/display.d.ts +16 -0
  215. package/dist/utils/display.js +42 -0
  216. package/dist/utils/exitCodes.d.ts +1 -0
  217. package/dist/utils/exitCodes.js +6 -0
  218. package/dist/utils/http.d.ts +9 -2
  219. package/dist/utils/http.js +4 -3
  220. package/dist/utils/process.d.ts +12 -0
  221. package/dist/utils/process.js +25 -0
  222. package/dist/utils/strings.d.ts +19 -0
  223. package/dist/utils/strings.js +16 -0
  224. package/package.json +2 -2
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Checks for a directory bdg is about to create and write (the session
3
+ * directory, a Chrome profile) before it touches it: `fs.mkdirSync` with
4
+ * `recursive` spins forever on Linux pseudo-filesystems (`/proc/x` kept a
5
+ * start at full CPU until SIGKILL), and a profile Chrome cannot use wedges
6
+ * the session.
7
+ */
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
10
+ /** Pseudo-filesystems no directory can be created on */
11
+ const PSEUDO_FILESYSTEM = /^\/(proc|sys)(\/|$)/;
12
+ /**
13
+ * Nearest path at or above `dir` that exists.
14
+ *
15
+ * @param dir - Absolute path
16
+ * @returns The path itself, or its nearest existing ancestor
17
+ */
18
+ function nearestExisting(dir) {
19
+ let current = dir;
20
+ while (!fs.existsSync(current)) {
21
+ const parent = path.dirname(current);
22
+ if (parent === current)
23
+ return current;
24
+ current = parent;
25
+ }
26
+ return current;
27
+ }
28
+ /**
29
+ * Why `dir` cannot be created or written: it (or the path to it) is on a
30
+ * pseudo-filesystem, a part of it is a file, or its nearest existing
31
+ * directory is not writable.
32
+ *
33
+ * @param dir - Directory path (resolved against the working directory)
34
+ * @returns The problem, or null when the directory can be used
35
+ */
36
+ export function directoryProblem(dir) {
37
+ const resolved = path.resolve(dir);
38
+ const existing = nearestExisting(resolved);
39
+ let real;
40
+ try {
41
+ real = fs.realpathSync(existing);
42
+ }
43
+ catch (error) {
44
+ return { reason: error.code ?? String(error), denied: false };
45
+ }
46
+ if (PSEUDO_FILESYSTEM.test(resolved) || PSEUDO_FILESYSTEM.test(real)) {
47
+ const root = (PSEUDO_FILESYSTEM.exec(resolved) ?? PSEUDO_FILESYSTEM.exec(real))?.[0] ?? '';
48
+ return { reason: `${root.replace(/\/$/, '')} is a pseudo-filesystem`, denied: false };
49
+ }
50
+ if (!fs.statSync(real).isDirectory()) {
51
+ return {
52
+ reason: existing === resolved ? 'it is a file' : `${existing} is a file`,
53
+ denied: false,
54
+ };
55
+ }
56
+ try {
57
+ fs.accessSync(real, fs.constants.W_OK);
58
+ }
59
+ catch (error) {
60
+ const code = error.code ?? String(error);
61
+ return { reason: `${existing} is not writable (${code})`, denied: true };
62
+ }
63
+ return null;
64
+ }
65
+ /**
66
+ * Create a directory (and its parents) after {@link directoryProblem} found
67
+ * nothing wrong, so a pseudo-filesystem fails at once instead of spinning.
68
+ *
69
+ * @param dir - Directory to create
70
+ * @param mode - Permissions of the directories created
71
+ * @throws Error with `code` `EPSEUDOFS` (pseudo-filesystem), `ENOTDIR` (a
72
+ * file on the path), `EACCES` (not writable), or the `mkdir` error
73
+ */
74
+ export function makeDirectory(dir, mode) {
75
+ if (fs.existsSync(dir))
76
+ return;
77
+ const problem = directoryProblem(dir);
78
+ if (problem) {
79
+ const code = problem.denied
80
+ ? 'EACCES'
81
+ : /pseudo-filesystem/.test(problem.reason)
82
+ ? 'EPSEUDOFS'
83
+ : 'ENOTDIR';
84
+ throw Object.assign(new Error(problem.reason), { code });
85
+ }
86
+ fs.mkdirSync(dir, { recursive: true, ...(mode !== undefined && { mode }) });
87
+ }
88
+ //# sourceMappingURL=directories.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Whether Chrome can show a window, which decides the default of
3
+ * `--headless`.
4
+ */
5
+ /**
6
+ * Whether a display is available for Chrome's window: on Linux an X11 or
7
+ * Wayland display (`DISPLAY`, `WAYLAND_DISPLAY`; WSLg sets them too), on
8
+ * macOS the desktop unless the shell came in over SSH (`SSH_CONNECTION`,
9
+ * `SSH_TTY`) or runs in CI (`CI`, unless `false` or `0`). Servers, containers and CI stay headless.
10
+ *
11
+ * @param env - Environment variables
12
+ * @param platform - Operating system (`process.platform`)
13
+ * @returns True when Chrome should show a window by default
14
+ */
15
+ export declare function hasDisplay(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean;
16
+ //# sourceMappingURL=display.d.ts.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Whether Chrome can show a window, which decides the default of
3
+ * `--headless`.
4
+ */
5
+ /**
6
+ * Whether an environment variable is set and not empty.
7
+ *
8
+ * @param env - Environment variables
9
+ * @param name - Variable name
10
+ * @returns True when set to a non-empty value
11
+ */
12
+ function isSet(env, name) {
13
+ const value = env[name];
14
+ return value !== undefined && value !== '';
15
+ }
16
+ /**
17
+ * Whether the environment says it is CI: `CI` set to anything but `false`
18
+ * or `0` (`CI=false` is how a CI flag is turned off).
19
+ *
20
+ * @param env - Environment variables
21
+ * @returns True in CI
22
+ */
23
+ function isCi(env) {
24
+ return isSet(env, 'CI') && !['false', '0'].includes(env['CI']?.toLowerCase() ?? '');
25
+ }
26
+ /**
27
+ * Whether a display is available for Chrome's window: on Linux an X11 or
28
+ * Wayland display (`DISPLAY`, `WAYLAND_DISPLAY`; WSLg sets them too), on
29
+ * macOS the desktop unless the shell came in over SSH (`SSH_CONNECTION`,
30
+ * `SSH_TTY`) or runs in CI (`CI`, unless `false` or `0`). Servers, containers and CI stay headless.
31
+ *
32
+ * @param env - Environment variables
33
+ * @param platform - Operating system (`process.platform`)
34
+ * @returns True when Chrome should show a window by default
35
+ */
36
+ export function hasDisplay(env = process.env, platform = process.platform) {
37
+ if (platform === 'darwin') {
38
+ return !isSet(env, 'SSH_CONNECTION') && !isSet(env, 'SSH_TTY') && !isCi(env);
39
+ }
40
+ return isSet(env, 'DISPLAY') || isSet(env, 'WAYLAND_DISPLAY');
41
+ }
42
+ //# sourceMappingURL=display.js.map
@@ -53,6 +53,7 @@ export declare const EXIT_CODES: {
53
53
  readonly UNHANDLED_EXCEPTION: 104;
54
54
  readonly SIGNAL_HANDLER_ERROR: 105;
55
55
  readonly SESSION_START_FAILURE: 106;
56
+ readonly PAGE_CRASHED: 107;
56
57
  readonly SOFTWARE_ERROR: 110;
57
58
  readonly INTERRUPTED: 130;
58
59
  readonly TERMINATED: 143;
@@ -53,6 +53,7 @@ export const EXIT_CODES = {
53
53
  UNHANDLED_EXCEPTION: 104,
54
54
  SIGNAL_HANDLER_ERROR: 105,
55
55
  SESSION_START_FAILURE: 106,
56
+ PAGE_CRASHED: 107,
56
57
  SOFTWARE_ERROR: 110,
57
58
  INTERRUPTED: 130,
58
59
  TERMINATED: 143,
@@ -165,6 +166,11 @@ export const EXIT_CODE_REGISTRY = [
165
166
  name: 'SESSION_START_FAILURE',
166
167
  description: 'Session failed to start (Chrome launch or CDP connection)',
167
168
  },
169
+ {
170
+ code: EXIT_CODES.PAGE_CRASHED,
171
+ name: 'PAGE_CRASHED',
172
+ description: 'The page crashed (its renderer is gone); bdg page reload brings it back',
173
+ },
168
174
  {
169
175
  code: EXIT_CODES.SOFTWARE_ERROR,
170
176
  name: 'SOFTWARE_ERROR',
@@ -1,5 +1,12 @@
1
1
  import type { CDPTarget } from '../types.js';
2
2
  import type { Logger } from '../ui/logging/index.js';
3
+ /**
4
+ * Timeout for CDP HTTP requests in milliseconds.
5
+ *
6
+ * Chrome's HTTP API should respond quickly when running.
7
+ * A 5-second timeout helps detect when Chrome is not responding.
8
+ */
9
+ export declare const CDP_HTTP_TIMEOUT_MS = 5000;
3
10
  /**
4
11
  * Options for CDP HTTP target fetch.
5
12
  */
@@ -47,10 +54,10 @@ export type DevToolsProbe = {
47
54
  *
48
55
  * @param port - Chrome debugging port
49
56
  * @param logger - Optional logger for debug output
50
- * @param options - Host and HTTPS
57
+ * @param options - Host, HTTPS and request timeout
51
58
  * @returns What answered
52
59
  */
53
- export declare function probeDevToolsEndpoint(port: number, logger?: Logger, options?: Pick<FetchCDPTargetsOptions, 'host' | 'secure'>): Promise<DevToolsProbe>;
60
+ export declare function probeDevToolsEndpoint(port: number, logger?: Logger, options?: FetchCDPTargetsOptions): Promise<DevToolsProbe>;
54
61
  /**
55
62
  * The browser-level DevTools WebSocket URL of a Chrome (`/json/version`).
56
63
  *
@@ -6,7 +6,7 @@ import { getErrorMessage } from './errors.js';
6
6
  * Chrome's HTTP API should respond quickly when running.
7
7
  * A 5-second timeout helps detect when Chrome is not responding.
8
8
  */
9
- const CDP_HTTP_TIMEOUT_MS = 5000;
9
+ export const CDP_HTTP_TIMEOUT_MS = 5000;
10
10
  /**
11
11
  * Fetch CDP targets from Chrome's HTTP API.
12
12
  *
@@ -67,14 +67,15 @@ export async function fetchCDPTargets(port = DEFAULT_CDP_PORT, logger, options)
67
67
  *
68
68
  * @param port - Chrome debugging port
69
69
  * @param logger - Optional logger for debug output
70
- * @param options - Host and HTTPS
70
+ * @param options - Host, HTTPS and request timeout
71
71
  * @returns What answered
72
72
  */
73
73
  export async function probeDevToolsEndpoint(port, logger, options) {
74
74
  const url = `${options?.secure ? 'https' : 'http'}://${options?.host ?? HTTP_LOCALHOST}:${port}/json/version`;
75
+ const timeoutMs = options?.timeoutMs ?? CDP_HTTP_TIMEOUT_MS;
75
76
  let response;
76
77
  try {
77
- response = await fetch(url, { signal: AbortSignal.timeout(CDP_HTTP_TIMEOUT_MS) });
78
+ response = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
78
79
  }
79
80
  catch (error) {
80
81
  logger?.debug(`Chrome version request failed: ${getErrorMessage(error)} (${url})`);
@@ -52,4 +52,16 @@ export declare function killChromeProcess(pid: number, signal?: NodeJS.Signals):
52
52
  * @returns Command line, or null if unavailable (process gone, or unsupported platform)
53
53
  */
54
54
  export declare function getProcessCommand(pid: number): string | null;
55
+ /** A running process and its command line */
56
+ export interface ProcessEntry {
57
+ pid: number;
58
+ command: string;
59
+ }
60
+ /**
61
+ * Every running process with its command line: from `/proc` on Linux
62
+ * (minimal containers' BusyBox `ps` lacks `-o`), else from `ps` (macOS).
63
+ *
64
+ * @returns Processes, empty when they cannot be listed (Windows)
65
+ */
66
+ export declare function listProcesses(): ProcessEntry[];
55
67
  //# sourceMappingURL=process.d.ts.map
@@ -120,4 +120,29 @@ export function getProcessCommand(pid) {
120
120
  const command = result.stdout.trim();
121
121
  return command.length > 0 ? command : null;
122
122
  }
123
+ /**
124
+ * Every running process with its command line: from `/proc` on Linux
125
+ * (minimal containers' BusyBox `ps` lacks `-o`), else from `ps` (macOS).
126
+ *
127
+ * @returns Processes, empty when they cannot be listed (Windows)
128
+ */
129
+ export function listProcesses() {
130
+ if (process.platform === 'win32')
131
+ return [];
132
+ if (fs.existsSync('/proc/self/cmdline')) {
133
+ return fs
134
+ .readdirSync('/proc')
135
+ .filter((name) => /^\d+$/.test(name))
136
+ .map((name) => ({ pid: Number(name), command: getProcessCommand(Number(name)) ?? '' }))
137
+ .filter((entry) => entry.command !== '');
138
+ }
139
+ const result = spawnSync('ps', ['-A', '-ww', '-o', 'pid=,command='], { encoding: 'utf-8' });
140
+ if (result.error || result.status !== 0)
141
+ return [];
142
+ return result.stdout
143
+ .split('\n')
144
+ .map((line) => /^\s*(\d+)\s+(.*)$/.exec(line))
145
+ .filter((match) => match !== null)
146
+ .map(([, pid, command]) => ({ pid: Number(pid), command: command ?? '' }));
147
+ }
123
148
  //# sourceMappingURL=process.js.map
@@ -11,4 +11,23 @@
11
11
  * @returns Truncated text with ellipsis if needed
12
12
  */
13
13
  export declare function truncateByLength(text: string, maxLength?: number): string;
14
+ /**
15
+ * A text cut to a maximum length, with its original length when it was cut.
16
+ */
17
+ export interface CappedText {
18
+ /** The text, or its first `maxLength` characters */
19
+ text: string;
20
+ /** Original length, set only when the text was cut */
21
+ truncatedFrom?: number;
22
+ }
23
+ /**
24
+ * Cut a text to its first `maxLength` characters (UTF-16 code units),
25
+ * keeping the original length (the `truncatedFrom` of JSON output). A
26
+ * surrogate pair (an emoji) is never split: the cut ends before it.
27
+ *
28
+ * @param text - Text to cut
29
+ * @param maxLength - Characters kept (at most)
30
+ * @returns The text, with `truncatedFrom` when it was cut
31
+ */
32
+ export declare function capLength(text: string, maxLength: number): CappedText;
14
33
  //# sourceMappingURL=strings.d.ts.map
@@ -20,4 +20,20 @@ export function truncateByLength(text, maxLength = DEFAULT_MAX_LENGTH) {
20
20
  }
21
21
  return text.slice(0, maxLength - 1) + '…';
22
22
  }
23
+ /**
24
+ * Cut a text to its first `maxLength` characters (UTF-16 code units),
25
+ * keeping the original length (the `truncatedFrom` of JSON output). A
26
+ * surrogate pair (an emoji) is never split: the cut ends before it.
27
+ *
28
+ * @param text - Text to cut
29
+ * @param maxLength - Characters kept (at most)
30
+ * @returns The text, with `truncatedFrom` when it was cut
31
+ */
32
+ export function capLength(text, maxLength) {
33
+ if (text.length <= maxLength)
34
+ return { text };
35
+ const lastKept = text.charCodeAt(maxLength - 1);
36
+ const end = lastKept >= 0xd800 && lastKept <= 0xdbff ? maxLength - 1 : maxLength;
37
+ return { text: text.slice(0, end), truncatedFrom: text.length };
38
+ }
23
39
  //# sourceMappingURL=strings.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-debugger-cli",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "description": "DevTools telemetry in your terminal. For humans and agents. Direct WebSocket to Chrome's debugging port.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,7 +27,7 @@
27
27
  "validate:ts-version": "node -e \"const ts = require('typescript'); const v = ts.version.split('.'); if (parseInt(v[0]) < 5 || (parseInt(v[0]) === 5 && parseInt(v[1]) < 6)) { console.error('Requires TypeScript 5.6+, found:', ts.version); process.exit(1); } else { console.log('✅ TypeScript version:', ts.version); }\"",
28
28
  "check": "npm run format:check && npm run type-check && npm run lint",
29
29
  "check:enhanced": "npm run format:check && npm run type-check && npm run lint && npm run validate:module-type && npm run validate:ts-version",
30
- "test": "tsx --test 'src/**/__tests__/**/!(*.smoke).test.ts'",
30
+ "test": "tsx --test --test-timeout=120000 'src/**/__tests__/**/!(*.smoke).test.ts'",
31
31
  "test:watch": "tsx --test --watch 'src/**/__tests__/**/!(*.smoke).test.ts'",
32
32
  "test:coverage": "c8 npm test",
33
33
  "test:smoke": "tsx --test --test-concurrency=1 'src/__tests__/smoke/*.smoke.test.ts'",