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
@@ -9,7 +9,7 @@ import { writeOutputFile } from '../../shared/outputFile.js';
9
9
  import { CDPConnectionError } from '../../../connection/errors.js';
10
10
  import { CommandError } from '../../../errors/index.js';
11
11
  import { noNodesFoundError, elementNotVisibleError, elementZeroDimensionsError, } from '../../../errors/messages.js';
12
- import { callCDP } from '../../../ipc/client.js';
12
+ import { callBdgScript, callCDP } from '../../../ipc/client.js';
13
13
  import { DEEP_QUERY_JS, selectorArgsJS } from '../../../runtime/dom/targetNode.js';
14
14
  import { viewportOverride } from '../../../runtime/page/emulation.js';
15
15
  import { readSessionMetadata } from '../../../session/metadata.js';
@@ -26,7 +26,7 @@ const STABILITY_CHECK_INTERVAL_MS = 50;
26
26
  */
27
27
  async function waitForPostScrollStability() {
28
28
  const deadline = Date.now() + POST_SCROLL_MAX_WAIT_MS;
29
- await callCDP('Runtime.evaluate', {
29
+ await callBdgScript('Runtime.evaluate', {
30
30
  expression: `
31
31
  (() => {
32
32
  window.__bdg_scrollStability = {
@@ -66,7 +66,7 @@ async function waitForPostScrollStability() {
66
66
  });
67
67
  try {
68
68
  while (Date.now() < deadline) {
69
- const checkResult = await callCDP('Runtime.evaluate', {
69
+ const checkResult = await callBdgScript('Runtime.evaluate', {
70
70
  expression: `
71
71
  (() => {
72
72
  const state = window.__bdg_scrollStability;
@@ -91,7 +91,7 @@ async function waitForPostScrollStability() {
91
91
  log.debug('Post-scroll stability timeout, proceeding anyway');
92
92
  }
93
93
  finally {
94
- await callCDP('Runtime.evaluate', {
94
+ await callBdgScript('Runtime.evaluate', {
95
95
  expression: `
96
96
  (() => {
97
97
  const state = window.__bdg_scrollStability;
@@ -111,7 +111,7 @@ async function waitForPostScrollStability() {
111
111
  * position so it can be restored afterwards.
112
112
  */
113
113
  async function scrollToElement(selector) {
114
- const result = await callCDP('Runtime.evaluate', {
114
+ const result = await callBdgScript('Runtime.evaluate', {
115
115
  expression: `
116
116
  (() => {
117
117
  const el = (${DEEP_QUERY_JS})(${selectorArgsJS(selector)})[0];
@@ -133,7 +133,7 @@ async function scrollToElement(selector) {
133
133
  return { x: value.originalX ?? 0, y: value.originalY ?? 0 };
134
134
  }
135
135
  async function restoreScrollPosition(position) {
136
- await callCDP('Runtime.evaluate', {
136
+ await callBdgScript('Runtime.evaluate', {
137
137
  expression: `window.scrollTo(${position.x}, ${position.y})`,
138
138
  returnByValue: true,
139
139
  });
@@ -147,7 +147,7 @@ async function restoreScrollPosition(position) {
147
147
  * @returns Width and height in CSS px
148
148
  */
149
149
  async function windowSize(viewport) {
150
- const response = await callCDP('Runtime.evaluate', {
150
+ const response = await callBdgScript('Runtime.evaluate', {
151
151
  expression: '[window.innerWidth, window.innerHeight]',
152
152
  returnByValue: true,
153
153
  });
@@ -245,7 +245,7 @@ export async function capturePageScreenshot(outputPath, options = {}) {
245
245
  if (options.scroll) {
246
246
  originalScrollPosition = await scrollToElement(options.scroll);
247
247
  }
248
- const dprResponse = await callCDP('Runtime.evaluate', {
248
+ const dprResponse = await callBdgScript('Runtime.evaluate', {
249
249
  expression: 'window.devicePixelRatio',
250
250
  returnByValue: true,
251
251
  });
@@ -266,7 +266,7 @@ export async function capturePageScreenshot(outputPath, options = {}) {
266
266
  const restoreMetrics = await useUnitPixelRatio(devicePixelRatio, viewport);
267
267
  if (devicePixelRatio !== 1) {
268
268
  if (options.scroll) {
269
- await callCDP('Runtime.evaluate', {
269
+ await callBdgScript('Runtime.evaluate', {
270
270
  expression: `(${DEEP_QUERY_JS})(${selectorArgsJS(options.scroll)})[0]?.scrollIntoView({ block: 'center', behavior: 'instant' })`,
271
271
  returnByValue: true,
272
272
  });
@@ -461,7 +461,7 @@ async function measureInView(ref, padding) {
461
461
  const scrolledFrom = await scrollPosition();
462
462
  const dx = bounds.x + bounds.width / 2 - view.width / 2;
463
463
  const dy = bounds.y + bounds.height / 2 - view.height / 2;
464
- await callCDP('Runtime.evaluate', { expression: `window.scrollBy(${dx}, ${dy})` });
464
+ await callBdgScript('Runtime.evaluate', { expression: `window.scrollBy(${dx}, ${dy})` });
465
465
  try {
466
466
  box = await getElementBounds(ref);
467
467
  bounds = await captureArea(ref, box, padding);
@@ -501,7 +501,7 @@ async function restoreViewport() {
501
501
  * @returns Scroll offsets in CSS px
502
502
  */
503
503
  async function scrollPosition() {
504
- const response = await callCDP('Runtime.evaluate', {
504
+ const response = await callBdgScript('Runtime.evaluate', {
505
505
  expression: '[window.scrollX, window.scrollY]',
506
506
  returnByValue: true,
507
507
  });
@@ -544,7 +544,7 @@ async function captureArea(ref, bounds, padding) {
544
544
  async function paintedArea(ref, bounds) {
545
545
  const objectGroup = `bdg-shot-${process.pid}`;
546
546
  try {
547
- const resolved = await callCDP('DOM.resolveNode', { ...ref, objectGroup });
547
+ const resolved = await callBdgScript('DOM.resolveNode', { ...ref, objectGroup });
548
548
  const objectId = resolved.data?.result?.object
549
549
  .objectId;
550
550
  if (!objectId)
@@ -586,7 +586,7 @@ export async function captureElementScreenshot(outputPath, ref, options = {}) {
586
586
  const format = options.format ?? 'png';
587
587
  const quality = format === 'jpeg' ? (options.quality ?? 90) : undefined;
588
588
  const noResize = options.noResize ?? false;
589
- const dprResponse = await callCDP('Runtime.evaluate', {
589
+ const dprResponse = await callBdgScript('Runtime.evaluate', {
590
590
  expression: 'window.devicePixelRatio',
591
591
  returnByValue: true,
592
592
  });
@@ -17,19 +17,23 @@
17
17
  */
18
18
  import { Option } from 'commander';
19
19
  import { registerA11yCommands } from './a11y.js';
20
+ import { registerAuditCommand } from './audit.js';
20
21
  import { handleDomEval } from './eval.js';
21
22
  import { registerFormCommand } from './form.js';
22
23
  import { handleDomFrames } from './frames.js';
23
24
  import { DOM_GET_DEFAULT_SELECTOR, handleDomGet } from './get.js';
25
+ import { QUERY_CACHE_LIMIT } from './helpers/query.js';
24
26
  import { registerInspectCommand } from './inspect.js';
25
- import { registerAuditCommand } from './audit.js';
26
27
  import { registerLayoutCommand } from './layout.js';
27
28
  import { registerListenersCommand } from './listeners.js';
28
- import { handleDomQuery } from './query.js';
29
+ import { handleDomQuery, QUERY_LIST_LIMIT } from './query.js';
29
30
  import { handleDomScreenshot } from './screenshot.js';
30
31
  import { registerWaitCommand } from './wait.js';
31
32
  import { SELECTOR_OR_INDEX_ARGUMENT, SELECTOR_SCOPE_HELP, } from '../shared/commonOptions.js';
32
33
  import { integerOption, screenshotFormatOption } from '../shared/validation.js';
34
+ import { MAX_VALUE_LENGTH, QUERY_JSON_LIST_LIMIT } from '../../constants.js';
35
+ /** Help of `--full` on `dom eval` and the `eval` shortcut */
36
+ const EVAL_FULL_HELP = `Print the whole value (default: the first ${MAX_VALUE_LENGTH} characters; a string result in JSON too)`;
33
37
  /**
34
38
  * Register DOM telemetry commands on the root Commander program.
35
39
  */
@@ -49,6 +53,7 @@ export function registerDomCommands(program) {
49
53
  .command('query')
50
54
  .description('Find elements by CSS selector')
51
55
  .argument('<selector>', 'CSS selector (e.g., ".error", "#app", "button")')
56
+ .option('--limit <n>', `Matches to list (default: ${QUERY_LIST_LIMIT}, ${QUERY_JSON_LIST_LIMIT} with --json; 0 = all); the first ${QUERY_CACHE_LIMIT} (or more with a higher limit) are indexed`, integerOption(0))
52
57
  .option('-j, --json', 'Output as JSON')
53
58
  .addHelpText('after', SELECTOR_SCOPE_HELP)
54
59
  .action(async (selector, options) => {
@@ -59,6 +64,7 @@ export function registerDomCommands(program) {
59
64
  .description('Evaluate JavaScript expression in the page context')
60
65
  .argument('<script>', 'JavaScript to execute (e.g., "document.title", "window.location.href")')
61
66
  .option('--frame <frame>', 'Evaluate in an iframe, cross-origin ones included: index (from dom frames; 87 when stale), name/id attribute, or part of the name, id or URL')
67
+ .option('--full', EVAL_FULL_HELP)
62
68
  .option('-j, --json', 'Output as JSON')
63
69
  .action(async (script, options) => {
64
70
  await handleDomEval(script, options);
@@ -68,6 +74,7 @@ export function registerDomCommands(program) {
68
74
  .description('Shortcut for: bdg dom eval')
69
75
  .argument('<script>', 'JavaScript to execute')
70
76
  .option('--frame <frame>', 'Evaluate in an iframe (see dom frames)')
77
+ .option('--full', EVAL_FULL_HELP)
71
78
  .option('-j, --json', 'Output as JSON')
72
79
  .action(async (script, options) => {
73
80
  await handleDomEval(script, options);
@@ -84,7 +91,7 @@ export function registerDomCommands(program) {
84
91
  .description('Get semantic accessibility structure (default) or raw HTML (--raw)')
85
92
  .argument('[selectorOrIndex]', `${SELECTOR_OR_INDEX_ARGUMENT} (e.g. ".error", "#app", 0); default: ${DOM_GET_DEFAULT_SELECTOR}`)
86
93
  .option('--raw', 'Output raw HTML with all filtering options')
87
- .option('--full', 'Show all of the element text (default: the first 500 characters)')
94
+ .option('--full', `Show all of the element text (default: the first 500 characters); with --raw, all of the HTML (default: the first ${MAX_VALUE_LENGTH} characters)`)
88
95
  .option('--all', 'Get all matches (only with --raw)')
89
96
  .option('--index <n>', 'Element index if selector matches multiple (0-based)', integerOption(0))
90
97
  .addOption(new Option('--nth <n>', 'Alias of --index').argParser(integerOption(0)).hideHelp())
@@ -2,13 +2,31 @@
2
2
  * `bdg dom query` — find elements by CSS selector and populate the query cache.
3
3
  */
4
4
  import type { DomQueryCommandOptions } from '../shared/optionTypes.js';
5
+ import type { DomQueryResult } from '../../types.js';
6
+ /** Matches `dom query` lists without `--limit` (human output) */
7
+ export declare const QUERY_LIST_LIMIT = 50;
5
8
  /**
6
9
  * Handle `bdg dom query <selector>`.
7
10
  *
8
- * Runs the selector, caches the result set so later commands can reference
9
- * elements by index, and renders the result either as JSON or human output.
11
+ * Runs the selector, caches the described matches so later commands can
12
+ * reference elements by index, and lists the first `--limit` of them (50,
13
+ * or {@link QUERY_JSON_LIST_LIMIT} with `--json`; 0 = all) with the total
14
+ * count. The first {@link QUERY_CACHE_LIMIT} are indexed whatever is listed.
10
15
  * No match exits 83, like `dom get` and `dom a11y`, and clears the cache so
11
16
  * indices of an earlier query are not used by mistake.
12
17
  */
13
18
  export declare function handleDomQuery(selector: string, options: DomQueryCommandOptions): Promise<void>;
19
+ /**
20
+ * The matches to list: the first `limit` (all with 0), with how many were
21
+ * left out and, when not every match was described, how many can be used by
22
+ * index. Nothing is added when the limit cut nothing (a match that could not
23
+ * be described is just missing, as before). When more than
24
+ * {@link VIEWPORT_HINT_LIMIT} are listed, `viewportChecked` says that only
25
+ * the first ones have a viewport position.
26
+ *
27
+ * @param result - Query result with every described match
28
+ * @param limit - Matches to list (0 = all)
29
+ * @returns Result to output
30
+ */
31
+ export declare function listedMatches(result: DomQueryResult, limit: number): DomQueryResult;
14
32
  //# sourceMappingURL=query.d.ts.map
@@ -1,22 +1,30 @@
1
1
  /**
2
2
  * `bdg dom query` — find elements by CSS selector and populate the query cache.
3
3
  */
4
- import { noMatchesError, queryDOMElements } from './helpers/index.js';
4
+ import { noMatchesError, pageDocumentId, queryDOMElements } from './helpers/index.js';
5
+ import { VIEWPORT_HINT_LIMIT } from './helpers/query.js';
5
6
  import { runCommand } from '../shared/CommandRunner.js';
7
+ import { QUERY_JSON_LIST_LIMIT } from '../../constants.js';
6
8
  import { QueryCacheManager } from '../../session/QueryCacheManager.js';
7
9
  import { formatDomQuery } from '../../ui/formatters/dom.js';
8
10
  import { EXIT_CODES } from '../../utils/exitCodes.js';
11
+ /** Matches `dom query` lists without `--limit` (human output) */
12
+ export const QUERY_LIST_LIMIT = 50;
9
13
  /**
10
14
  * Handle `bdg dom query <selector>`.
11
15
  *
12
- * Runs the selector, caches the result set so later commands can reference
13
- * elements by index, and renders the result either as JSON or human output.
16
+ * Runs the selector, caches the described matches so later commands can
17
+ * reference elements by index, and lists the first `--limit` of them (50,
18
+ * or {@link QUERY_JSON_LIST_LIMIT} with `--json`; 0 = all) with the total
19
+ * count. The first {@link QUERY_CACHE_LIMIT} are indexed whatever is listed.
14
20
  * No match exits 83, like `dom get` and `dom a11y`, and clears the cache so
15
21
  * indices of an earlier query are not used by mistake.
16
22
  */
17
23
  export async function handleDomQuery(selector, options) {
24
+ const limit = options.limit ?? (options.json ? QUERY_JSON_LIST_LIMIT : QUERY_LIST_LIMIT);
18
25
  await runCommand(async () => {
19
- const result = await queryDOMElements(selector);
26
+ const document = await pageDocumentId();
27
+ const result = await queryDOMElements(selector, limit);
20
28
  const cache = QueryCacheManager.getInstance();
21
29
  if (result.count === 0) {
22
30
  await cache.clear();
@@ -28,8 +36,33 @@ export async function handleDomQuery(selector, options) {
28
36
  errorContext: { suggestion: err.suggestion },
29
37
  };
30
38
  }
31
- await cache.set(result);
32
- return { success: true, data: result };
39
+ await cache.set(result, document);
40
+ return { success: true, data: listedMatches(result, limit) };
33
41
  }, options, formatDomQuery);
34
42
  }
43
+ /**
44
+ * The matches to list: the first `limit` (all with 0), with how many were
45
+ * left out and, when not every match was described, how many can be used by
46
+ * index. Nothing is added when the limit cut nothing (a match that could not
47
+ * be described is just missing, as before). When more than
48
+ * {@link VIEWPORT_HINT_LIMIT} are listed, `viewportChecked` says that only
49
+ * the first ones have a viewport position.
50
+ *
51
+ * @param result - Query result with every described match
52
+ * @param limit - Matches to list (0 = all)
53
+ * @returns Result to output
54
+ */
55
+ export function listedMatches(result, limit) {
56
+ const listed = limit === 0 || result.count <= limit
57
+ ? result
58
+ : {
59
+ ...result,
60
+ nodes: result.nodes.slice(0, limit),
61
+ omitted: result.count - Math.min(limit, result.nodes.length),
62
+ ...(result.nodes.length < result.count && { indexed: result.nodes.length }),
63
+ };
64
+ return listed.nodes.length > VIEWPORT_HINT_LIMIT
65
+ ? { ...listed, viewportChecked: VIEWPORT_HINT_LIMIT }
66
+ : listed;
67
+ }
35
68
  //# sourceMappingURL=query.js.map
@@ -14,6 +14,7 @@ import { OutputBuilder, buildSuccessResponse } from '../../ui/OutputBuilder.js';
14
14
  import { formatDomScreenshot } from '../../ui/formatters/dom.js';
15
15
  import { createLogger } from '../../ui/logging/index.js';
16
16
  import { delay } from '../../utils/async.js';
17
+ import { makeDirectory } from '../../utils/directories.js';
17
18
  import { getErrorMessage } from '../../utils/errors.js';
18
19
  import { EXIT_CODES } from '../../utils/exitCodes.js';
19
20
  import { filterDefined } from '../../utils/objects.js';
@@ -110,7 +111,7 @@ function ensureDirectory(dirPath, fs) {
110
111
  throw new CommandError(`--follow needs a directory, but ${dirPath} is a file`, { suggestion: 'Give a directory for the frames, e.g. bdg dom screenshot ./frames --follow' }, EXIT_CODES.INVALID_ARGUMENTS);
111
112
  }
112
113
  try {
113
- fs.mkdirSync(dirPath, { recursive: true });
114
+ makeDirectory(dirPath);
114
115
  }
115
116
  catch (error) {
116
117
  throw outputPathError(dirPath, error);
@@ -188,6 +189,7 @@ async function handleSequenceCapture(outputDir, options) {
188
189
  /**
189
190
  * End a capture sequence on an error (e.g. the element disappeared): print
190
191
  * it (one JSON line with `--json`, like the frames) and exit with its code.
192
+ * It stays compact on a terminal too, since it ends the NDJSON frame stream.
191
193
  *
192
194
  * @param error - Capture error
193
195
  * @param captured - Frames captured before it
@@ -21,10 +21,11 @@ export interface SemanticNodeWithContext {
21
21
  * link's href, a field's type and name), like `dom query` does, and is
22
22
  * followed by up to 500 characters of the element's text
23
23
  * (all of it with `dom get --full`) when it is longer than the one-line
24
- * preview, or, for an element without text or name, what it holds.
24
+ * preview or the role line shows an accessible name other than the text,
25
+ * or, for an element without text or name, what it holds.
25
26
  *
26
27
  * @param data - Accessibility node and optional DOM context
27
- * @returns Role line, plus a text line for elements with longer text
28
+ * @returns Role line, plus a text line for elements with longer or differently named text
28
29
  */
29
30
  export declare function formatSemanticNodeWithContext(data: SemanticNodeWithContext): string;
30
31
  /**
@@ -5,7 +5,7 @@
5
5
  * their surrounding DOM context and to fall back gracefully when only one
6
6
  * of the two data sources is available.
7
7
  */
8
- import { MASKED_VALUE } from '../../runtime/dom/elementInfo.js';
8
+ import { MASKED_VALUE, isLabelClass } from '../../runtime/dom/elementInfo.js';
9
9
  import { synthesizeA11yNode } from '../../telemetry/roleInference.js';
10
10
  import { keyAttributeItems } from '../../ui/formatters/keyAttributes.js';
11
11
  import { joinLines } from '../../ui/formatting.js';
@@ -29,9 +29,8 @@ function buildContextText(node, domContext) {
29
29
  }
30
30
  if (domContext) {
31
31
  const tagPart = `<${domContext.tag}`;
32
- const classPart = domContext.classes && domContext.classes.length > 0
33
- ? `.${domContext.classes.slice(0, 3).join('.')}`
34
- : '';
32
+ const classes = (domContext.classes ?? []).filter(isLabelClass).slice(0, 3);
33
+ const classPart = classes.length > 0 ? `.${classes.join('.')}` : '';
35
34
  const previewPart = domContext.preview && !domContext.text ? ` "${domContext.preview}"` : '';
36
35
  return ` ${tagPart}${classPart}>${previewPart}`;
37
36
  }
@@ -86,10 +85,11 @@ function buildPropertiesText(node) {
86
85
  * link's href, a field's type and name), like `dom query` does, and is
87
86
  * followed by up to 500 characters of the element's text
88
87
  * (all of it with `dom get --full`) when it is longer than the one-line
89
- * preview, or, for an element without text or name, what it holds.
88
+ * preview or the role line shows an accessible name other than the text,
89
+ * or, for an element without text or name, what it holds.
90
90
  *
91
91
  * @param data - Accessibility node and optional DOM context
92
- * @returns Role line, plus a text line for elements with longer text
92
+ * @returns Role line, plus a text line for elements with longer or differently named text
93
93
  */
94
94
  export function formatSemanticNodeWithContext(data) {
95
95
  const { node, domContext } = data;
@@ -99,13 +99,44 @@ export function formatSemanticNodeWithContext(data) {
99
99
  const propsText = buildPropertiesText(node);
100
100
  const inferredText = node.inferred ? ' (inferred from DOM)' : '';
101
101
  const line = `${roleText}${contextText}${keysText}${propsText}${inferredText}`;
102
- if (domContext?.text)
103
- return joinLines(line, elementTextLine(domContext.text));
102
+ const text = textNotOnRoleLine(node, domContext);
103
+ if (text)
104
+ return joinLines(line, elementTextLine(text));
104
105
  if (domContext?.childCount !== undefined && !node.name) {
105
- return joinLines(line, emptyElementLine(domContext.children ?? [], domContext.childCount));
106
+ return joinLines(line, emptyElementLine(domContext.children ?? [], domContext.childCount, domContext.shadowChildren));
106
107
  }
107
108
  return line;
108
109
  }
110
+ /**
111
+ * The element's text when the role line does not show it: text longer than
112
+ * the one-line preview, or the visible text of an element whose accessible
113
+ * name is something else (an editor named by its aria-label), unless its
114
+ * name or value shows that text (a long heading with inline children is
115
+ * named by all of it). Texts are compared ignoring case and whitespace.
116
+ * A sensitive field's text is never shown.
117
+ *
118
+ * @param node - Accessibility node
119
+ * @param domContext - DOM context with the text
120
+ * @returns Text for the text line, or undefined
121
+ */
122
+ function textNotOnRoleLine(node, domContext) {
123
+ if (domContext?.sensitive)
124
+ return undefined;
125
+ const text = domContext?.text ?? (node.name ? domContext?.preview : undefined);
126
+ if (!text)
127
+ return undefined;
128
+ const shown = [node.name, node.value].map((value) => comparableText(value ?? ''));
129
+ return shown.includes(comparableText(text)) ? undefined : text;
130
+ }
131
+ /**
132
+ * Text in the form texts are compared in.
133
+ *
134
+ * @param text - Text
135
+ * @returns Lowercased text with whitespace collapsed
136
+ */
137
+ function comparableText(text) {
138
+ return text.replace(/\s+/g, ' ').trim().toLowerCase();
139
+ }
109
140
  /**
110
141
  * Resolve an a11y node, falling back to a DOM-synthesized one when only
111
142
  * DOM context is available. Returns null when neither source can produce one.
@@ -78,9 +78,30 @@ export interface CommandMetadata {
78
78
  arguments: ArgumentMetadata[];
79
79
  /** Command options */
80
80
  options: OptionMetadata[];
81
+ /** Text shown after the options in `--help` (examples, output legend) */
82
+ helpText?: string;
81
83
  /** Subcommands */
82
84
  subcommands: CommandMetadata[];
83
85
  }
86
+ /**
87
+ * Command summary for the compact root help: one-line description, arguments
88
+ * and flags with their descriptions (behaviors, defaults and choices are in
89
+ * `bdg <command> --help --json`).
90
+ */
91
+ export interface CompactCommand {
92
+ /** Command name */
93
+ name: string;
94
+ /** Command aliases (only when it has some) */
95
+ aliases?: readonly string[];
96
+ /** First line of the description */
97
+ description: string;
98
+ /** Arguments as in usage, e.g. "<selector> [index]" (only when it takes some) */
99
+ arguments?: string;
100
+ /** Visible options: flags to description */
101
+ options?: Record<string, string>;
102
+ /** Subcommands (only for command groups) */
103
+ subcommands?: CompactCommand[];
104
+ }
84
105
  /**
85
106
  * Runtime state information for dynamic command availability.
86
107
  */
@@ -112,7 +133,7 @@ export interface Capabilities {
112
133
  };
113
134
  }
114
135
  /**
115
- * Root machine-readable help structure.
136
+ * Root machine-readable help structure (`bdg --help --json --full`).
116
137
  */
117
138
  export interface MachineReadableHelp {
118
139
  /** CLI name */
@@ -142,10 +163,34 @@ export interface MachineReadableHelp {
142
163
  capabilities: Capabilities;
143
164
  }
144
165
  /**
145
- * Generates machine-readable help from a Commander program.
166
+ * Compact root help (`bdg --help --json`): the full help with a command tree
167
+ * of names, one-line descriptions and flags.
168
+ */
169
+ export interface CompactHelp extends Omit<MachineReadableHelp, 'command'> {
170
+ /** Where the details are */
171
+ details: string;
172
+ /** Root command summary */
173
+ command: CompactCommand;
174
+ }
175
+ /**
176
+ * Help for one command (`bdg <command> --help --json`): its full metadata
177
+ * (option behaviors, defaults, choices, help text), its subcommands in compact
178
+ * form, and the exit codes.
179
+ */
180
+ export interface CommandHelp extends Pick<MachineReadableHelp, 'name' | 'version' | 'description' | 'exitCodes'> {
181
+ /** Full command path, e.g. "bdg dom query" */
182
+ path: string;
183
+ /** Command metadata; subcommands summarized (ask each for its details) */
184
+ command: Omit<CommandMetadata, 'subcommands'> & {
185
+ subcommands: CompactCommand[];
186
+ };
187
+ }
188
+ /**
189
+ * Generates the full machine-readable help from a Commander program
190
+ * (`bdg --help --json --full`).
146
191
  *
147
192
  * Includes comprehensive metadata for agent discovery:
148
- * - Command structure and options
193
+ * - Command structure and options with behaviors
149
194
  * - Exit codes with semantic meanings
150
195
  * - Task-to-command mappings with CDP alternatives
151
196
  * - Runtime state and command availability
@@ -154,34 +199,52 @@ export interface MachineReadableHelp {
154
199
  *
155
200
  * @param program - Commander program instance
156
201
  * @returns Machine-readable help structure
202
+ */
203
+ export declare function generateMachineReadableHelp(program: Command): MachineReadableHelp;
204
+ /**
205
+ * Generates the compact root help (`bdg --help --json`): the full help with
206
+ * the command tree reduced to names, one-line descriptions and flags.
207
+ *
208
+ * @param program - Commander program instance
209
+ * @returns Compact help structure
210
+ */
211
+ export declare function generateCompactHelp(program: Command): CompactHelp;
212
+ /**
213
+ * The command a command line addresses: follows the words that name
214
+ * subcommands and skips the others (option values, arguments), stopping at a
215
+ * command without subcommands.
216
+ *
217
+ * @param program - Root Commander program instance
218
+ * @param words - Command-line words, e.g. ['dom', 'query', '.item']
219
+ * @returns The addressed command (the program when no word names one)
157
220
  *
158
221
  * @example
159
222
  * ```typescript
160
- * import { program } from 'commander';
161
- * import { generateMachineReadableHelp } from './help/machineReadableHelp.js';
162
- *
163
- * const help = generateMachineReadableHelp(program);
164
- * console.log(JSON.stringify(help, null, 2));
223
+ * resolveCommand(program, ['--session', 'a', 'dom', 'query', '.item']).name(); // 'query'
165
224
  * ```
166
225
  */
167
- export declare function generateMachineReadableHelp(program: Command): MachineReadableHelp;
226
+ export declare function resolveCommand(program: Command, words: string[]): Command;
168
227
  /**
169
- * Generates machine-readable help for a specific subcommand.
228
+ * Full command path, e.g. "bdg dom query".
170
229
  *
171
- * Returns the same structure as generateMachineReadableHelp but with
172
- * the command field focused on the requested subcommand. If the subcommand
173
- * is not found, falls back to full root help.
230
+ * @param command - Commander command instance
231
+ * @returns Names from the program down to the command
232
+ */
233
+ export declare function commandPath(command: Command): string;
234
+ /**
235
+ * Generates machine-readable help for one command: its full metadata,
236
+ * compact subcommands (a group lists them like the root help does) and the
237
+ * exit codes.
174
238
  *
175
239
  * @param program - Root Commander program instance
176
- * @param commandPath - Array of command names (e.g., ['dom', 'query'])
177
- * @returns Machine-readable help structure for the subcommand
240
+ * @param command - The command (from {@link resolveCommand})
241
+ * @returns Help for the command
178
242
  *
179
243
  * @example
180
244
  * ```typescript
181
- * // Get help for 'bdg dom query'
182
- * const help = generateSubcommandHelp(program, ['dom', 'query']);
183
- * console.log(help.command.name); // 'query'
245
+ * const help = generateCommandHelp(program, resolveCommand(program, ['dom', 'query']));
246
+ * console.log(help.path); // 'bdg dom query'
184
247
  * ```
185
248
  */
186
- export declare function generateSubcommandHelp(program: Command, commandPath: string[]): MachineReadableHelp;
249
+ export declare function generateCommandHelp(program: Command, command: Command): CommandHelp;
187
250
  //# sourceMappingURL=helpJson.d.ts.map