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
@@ -2,15 +2,40 @@
2
2
  * Smart summary view: prioritises errors and warnings with deduplication
3
3
  * and shows info/debug/other as count-only footer entries.
4
4
  */
5
+ import { MAX_CONSOLE_TEXT_LENGTH } from '../../../constants.js';
6
+ import { capForDisplay } from '../longValues.js';
5
7
  import { OutputFormatter, pluralize } from '../../formatting.js';
6
- import { analyzeMessages, formatCountPrefix, formatSectionHeader, formatSourceLocation, } from './shared.js';
7
- function renderErrorSection(fmt, errors, total) {
8
+ import { consoleDroppedNote, consoleMoreGroupsNote } from '../../messages/consoleMessages.js';
9
+ import { analyzeMessages, formatCountPrefix, formatSectionHeader, formatSourceLocation, newestGroups, } from './shared.js';
10
+ /**
11
+ * A message's text cut like `console --list` cuts it, or whole with `--full`.
12
+ *
13
+ * @param message - Message
14
+ * @param full - `--full`
15
+ * @returns Text to print
16
+ */
17
+ function messageText(message, full) {
18
+ return capForDisplay(message.text, MAX_CONSOLE_TEXT_LENGTH, full);
19
+ }
20
+ /**
21
+ * The errors: the newest distinct ones, with a note for the earlier ones.
22
+ *
23
+ * @param fmt - Output
24
+ * @param errors - Distinct errors in order of first appearance
25
+ * @param total - Errors logged
26
+ * @param limit - Distinct errors listed (0 = all)
27
+ * @param full - Print the texts whole (`--full`)
28
+ */
29
+ function renderErrorSection(fmt, errors, total, limit, full) {
8
30
  if (errors.length === 0)
9
31
  return;
32
+ const { shown, more } = newestGroups(errors, limit);
10
33
  fmt.text(formatSectionHeader('Errors', errors.length, total));
11
34
  fmt.separator('─', 30);
12
- for (const { message, count } of errors) {
13
- fmt.text(`${formatCountPrefix(count)}${message.text}`);
35
+ if (more > 0)
36
+ fmt.text(consoleMoreGroupsNote(more, 'error')).blank();
37
+ for (const { message, count } of shown) {
38
+ fmt.text(`${formatCountPrefix(count)}${messageText(message, full)}`);
14
39
  const source = formatSourceLocation(message.stackTrace);
15
40
  if (source) {
16
41
  fmt.text(` → ${source}`);
@@ -18,13 +43,25 @@ function renderErrorSection(fmt, errors, total) {
18
43
  fmt.blank();
19
44
  }
20
45
  }
21
- function renderWarningSection(fmt, warnings, total) {
46
+ /**
47
+ * The warnings: the newest distinct ones, with a note for the earlier ones.
48
+ *
49
+ * @param fmt - Output
50
+ * @param warnings - Distinct warnings in order of first appearance
51
+ * @param total - Warnings logged
52
+ * @param limit - Distinct warnings listed (0 = all)
53
+ * @param full - Print the texts whole (`--full`)
54
+ */
55
+ function renderWarningSection(fmt, warnings, total, limit, full) {
22
56
  if (warnings.length === 0)
23
57
  return;
58
+ const { shown, more } = newestGroups(warnings, limit);
24
59
  fmt.text(formatSectionHeader('Warnings', warnings.length, total));
25
60
  fmt.separator('─', 30);
26
- for (const { message, count } of warnings) {
27
- fmt.text(`• ${formatCountPrefix(count)}${message.text}`);
61
+ if (more > 0)
62
+ fmt.text(consoleMoreGroupsNote(more, 'warning'));
63
+ for (const { message, count } of shown) {
64
+ fmt.text(`• ${formatCountPrefix(count)}${messageText(message, full)}`);
28
65
  const source = formatSourceLocation(message.stackTrace);
29
66
  if (source)
30
67
  fmt.text(` → ${source}`);
@@ -43,16 +80,25 @@ function renderOtherSummary(fmt, summary) {
43
80
  }
44
81
  }
45
82
  /**
46
- * Format console output as smart summary (default mode).
83
+ * Format console output as smart summary (default mode): the newest distinct
84
+ * errors and warnings, counts of the rest, and a note when the session
85
+ * dropped its oldest messages.
86
+ *
87
+ * @param messages - Messages to summarise
88
+ * @param options - Distinct messages listed, messages dropped and `--full`
89
+ * @returns Summary
47
90
  */
48
- export function formatConsoleSummary(messages) {
91
+ export function formatConsoleSummary(messages, options = {}) {
49
92
  const fmt = new OutputFormatter();
50
93
  const { grouped, summary } = analyzeMessages(messages);
51
94
  fmt.text('Console Summary');
52
95
  fmt.separator('━', 60);
96
+ if (options.dropped)
97
+ fmt.text(consoleDroppedNote(options.dropped));
53
98
  fmt.blank();
54
- renderErrorSection(fmt, grouped.errors, summary.errors.total);
55
- renderWarningSection(fmt, grouped.warnings, summary.warnings.total);
99
+ const { groupLimit, full } = options;
100
+ renderErrorSection(fmt, grouped.errors, summary.errors.total, groupLimit, full);
101
+ renderWarningSection(fmt, grouped.warnings, summary.warnings.total, groupLimit, full);
56
102
  if (grouped.errors.length === 0 && grouped.warnings.length === 0) {
57
103
  fmt.text('No errors or warnings found');
58
104
  fmt.blank();
@@ -11,12 +11,13 @@ export type { ConsoleFormatOptions, ConsoleJsonOutput, ConsoleLevel, ConsoleSkip
11
11
  export { LEVEL_MAP } from './console/shared.js';
12
12
  export { formatConsoleChronological, lastMessages } from './console/chronological.js';
13
13
  export { formatConsoleFollowLines } from './console/follow.js';
14
- export { buildConsoleJsonOutput, formatConsoleJson } from './console/json.js';
14
+ export { buildConsoleJsonOutput } from './console/json.js';
15
15
  export { formatConsoleSummary } from './console/summarize.js';
16
16
  /**
17
17
  * Format console output based on options. Routes to the per-mode formatter:
18
18
  * a `--level` filter lists the matching messages (the summary only shows
19
- * errors and warnings, so it would hide e.g. `--level info`).
19
+ * errors and warnings, so it would hide e.g. `--level info`). The text
20
+ * starts with a warning when the page crashed.
20
21
  */
21
22
  export declare function formatConsole(messages: ConsoleMessage[], options: ConsoleFormatOptions): string;
22
23
  //# sourceMappingURL=console.d.ts.map
@@ -5,26 +5,24 @@
5
5
  * the `formatConsole` dispatcher. The per-mode implementations live in
6
6
  * `./console/`.
7
7
  */
8
+ import { withPageCrashedNote } from '../messages/commands.js';
8
9
  import { formatConsoleChronological } from './console/chronological.js';
9
- import { formatConsoleJson } from './console/json.js';
10
10
  import { formatConsoleSummary } from './console/summarize.js';
11
11
  export { LEVEL_MAP } from './console/shared.js';
12
12
  export { formatConsoleChronological, lastMessages } from './console/chronological.js';
13
13
  export { formatConsoleFollowLines } from './console/follow.js';
14
- export { buildConsoleJsonOutput, formatConsoleJson } from './console/json.js';
14
+ export { buildConsoleJsonOutput } from './console/json.js';
15
15
  export { formatConsoleSummary } from './console/summarize.js';
16
16
  /**
17
17
  * Format console output based on options. Routes to the per-mode formatter:
18
18
  * a `--level` filter lists the matching messages (the summary only shows
19
- * errors and warnings, so it would hide e.g. `--level info`).
19
+ * errors and warnings, so it would hide e.g. `--level info`). The text
20
+ * starts with a warning when the page crashed.
20
21
  */
21
22
  export function formatConsole(messages, options) {
22
- if (options.json) {
23
- return formatConsoleJson(messages, options);
24
- }
25
- if (options.list || options.level) {
26
- return formatConsoleChronological(messages, options);
27
- }
28
- return formatConsoleSummary(messages);
23
+ const body = options.list || options.level
24
+ ? formatConsoleChronological(messages, options)
25
+ : formatConsoleSummary(messages, options);
26
+ return withPageCrashedNote(body, options.pageCrashedAt);
29
27
  }
30
28
  //# sourceMappingURL=console.js.map
@@ -1,4 +1,4 @@
1
- import { skippedBodyReason } from '../../telemetry/network.js';
1
+ import { skippedBodyReason } from '../../telemetry/networkRetention.js';
2
2
  import { formatFramePosition, formatTimestamp } from './console/shared.js';
3
3
  import { headerValueLines } from './networkHeaders.js';
4
4
  import { formatRequestStatus } from './requestStatus.js';
@@ -184,13 +184,15 @@ function requestSummaryRows(request) {
184
184
  }
185
185
  /**
186
186
  * Add a header block, a header sent several times one value per line
187
- * ({@link headerValueLines}).
187
+ * ({@link headerValueLines}); nothing when there are no headers.
188
188
  *
189
189
  * @param fmt - Formatter
190
190
  * @param title - Block title
191
191
  * @param headers - Headers to list
192
192
  */
193
193
  function addHeaders(fmt, title, headers) {
194
+ if (Object.keys(headers).length === 0)
195
+ return;
194
196
  fmt.text(title).separator('━', 70);
195
197
  Object.entries(headers).forEach(([key, value]) => headerValueLines(key, value).forEach((line) => fmt.text(` ${key}: ${line}`)));
196
198
  fmt.blank();
@@ -6,7 +6,7 @@ import type { DomQueryResult, DomGetResult, ScreenshotResult } from '../../types
6
6
  * Displays found nodes with their index, tag, identifying attributes
7
7
  * ({@link queryTagAttributes}), classes, and preview text
8
8
  * (plus where they are when outside the viewport or hidden, e.g.
9
- * `(below fold)`), up to {@link QUERY_DISPLAY_LIMIT} of them (no match is an error, exit 83).
9
+ * `(below fold)`), as many as `--limit` listed, with a note for the rest (no match is an error, exit 83).
10
10
  * One line of next commands follows; they take the match's index, so they
11
11
  * work for matches in shadow roots and iframes too.
12
12
  *
@@ -33,10 +33,13 @@ export declare function formatDomQuery(data: DomQueryResult): string;
33
33
  /**
34
34
  * Format DOM get results for human-readable output.
35
35
  *
36
- * Displays full outerHTML for matched elements. For single elements, shows HTML directly.
37
- * For multiple elements, shows numbered list with HTML for each.
36
+ * Displays the outerHTML of matched elements, each cut to its first
37
+ * {@link MAX_VALUE_LENGTH} characters with a pointer naming `--full`. For
38
+ * single elements, shows HTML directly. For multiple elements, shows
39
+ * numbered list with HTML for each.
38
40
  *
39
41
  * @param data - DOM get result containing array of nodes with outerHTML
42
+ * @param options - `full` to print the HTML whole
40
43
  * @returns Formatted output string
41
44
  *
42
45
  * @example
@@ -59,7 +62,9 @@ export declare function formatDomQuery(data: DomQueryResult): string;
59
62
  * // [1] <span class="error">Error 2</span>
60
63
  * ```
61
64
  */
62
- export declare function formatDomGet(data: DomGetResult): string;
65
+ export declare function formatDomGet(data: DomGetResult, options?: {
66
+ full?: boolean | undefined;
67
+ }): string;
63
68
  /**
64
69
  * Format DOM eval results for human-readable output.
65
70
  *
@@ -69,9 +74,11 @@ export declare function formatDomGet(data: DomGetResult): string;
69
74
  * JSON-quoted. Other values are formatted JSON, and values Chrome only
70
75
  * describes (functions, DOM nodes) their description. The iframe it ran in
71
76
  * (`--frame`) is reported on stderr, so stdout stays the bare value. `--json`
72
- * output is unchanged (the value in `data.result`).
77
+ * output is unchanged (the value in `data.result`). The text is cut to its
78
+ * first {@link MAX_VALUE_LENGTH} characters with a pointer naming `--full`.
73
79
  *
74
80
  * @param data - DOM eval result containing the evaluated value
81
+ * @param options - `full` to print the value whole
75
82
  * @returns The string, or formatted JSON
76
83
  *
77
84
  * @example
@@ -90,6 +97,8 @@ export declare function formatDomGet(data: DomGetResult): string;
90
97
  export declare function formatDomEval(data: {
91
98
  result: unknown;
92
99
  type?: string;
100
+ }, options?: {
101
+ full?: boolean | undefined;
93
102
  }): string;
94
103
  /**
95
104
  * Format the page's iframes, one per line, nested frames indented below
@@ -1,15 +1,15 @@
1
+ import { MAX_VALUE_LENGTH } from '../../constants.js';
1
2
  import { keyAttributeItems } from './keyAttributes.js';
3
+ import { capForDisplay } from './longValues.js';
2
4
  import { OutputFormatter } from '../formatting.js';
3
- import { frameLabel, moreMatchesNote, framesStillLoadingNote, noFramesMessage, queryNextSteps, screenshotGrownNote, screenshotScaledNote, viewportPositionHint, } from '../messages/commands.js';
4
- /** Matches listed in human output (JSON has all of them) */
5
- const QUERY_DISPLAY_LIMIT = 50;
5
+ import { frameLabel, framesStillLoadingNote, noFramesMessage, queryMoreMatchesNote, queryViewportCheckedNote, queryNextSteps, screenshotGrownNote, screenshotScaledNote, viewportPositionHint, } from '../messages/commands.js';
6
6
  /**
7
7
  * Format DOM query results for human-readable output.
8
8
  *
9
9
  * Displays found nodes with their index, tag, identifying attributes
10
10
  * ({@link queryTagAttributes}), classes, and preview text
11
11
  * (plus where they are when outside the viewport or hidden, e.g.
12
- * `(below fold)`), up to {@link QUERY_DISPLAY_LIMIT} of them (no match is an error, exit 83).
12
+ * `(below fold)`), as many as `--limit` listed, with a note for the rest (no match is an error, exit 83).
13
13
  * One line of next commands follows; they take the match's index, so they
14
14
  * work for matches in shadow roots and iframes too.
15
15
  *
@@ -35,7 +35,7 @@ const QUERY_DISPLAY_LIMIT = 50;
35
35
  export function formatDomQuery(data) {
36
36
  const { count, nodes, selector } = data;
37
37
  const fmt = new OutputFormatter();
38
- const nodeLines = nodes.slice(0, QUERY_DISPLAY_LIMIT).map((node) => {
38
+ const nodeLines = nodes.map((node) => {
39
39
  const attributes = queryTagAttributes(node)
40
40
  .map((item) => ` ${item}`)
41
41
  .join('');
@@ -49,7 +49,8 @@ export function formatDomQuery(data) {
49
49
  return fmt
50
50
  .text(`Found ${count} node${count === 1 ? '' : 's'} matching "${selector}":`)
51
51
  .list(nodeLines)
52
- .list(count > QUERY_DISPLAY_LIMIT ? [moreMatchesNote(count - QUERY_DISPLAY_LIMIT)] : [])
52
+ .list(data.omitted ? [queryMoreMatchesNote(data.omitted, data.indexed)] : [])
53
+ .list(data.viewportChecked ? [queryViewportCheckedNote(data.viewportChecked)] : [])
53
54
  .tip(queryNextSteps(exampleIndex))
54
55
  .build();
55
56
  }
@@ -76,10 +77,13 @@ function queryTagAttributes(node) {
76
77
  /**
77
78
  * Format DOM get results for human-readable output.
78
79
  *
79
- * Displays full outerHTML for matched elements. For single elements, shows HTML directly.
80
- * For multiple elements, shows numbered list with HTML for each.
80
+ * Displays the outerHTML of matched elements, each cut to its first
81
+ * {@link MAX_VALUE_LENGTH} characters with a pointer naming `--full`. For
82
+ * single elements, shows HTML directly. For multiple elements, shows
83
+ * numbered list with HTML for each.
81
84
  *
82
85
  * @param data - DOM get result containing array of nodes with outerHTML
86
+ * @param options - `full` to print the HTML whole
83
87
  * @returns Formatted output string
84
88
  *
85
89
  * @example
@@ -102,15 +106,16 @@ function queryTagAttributes(node) {
102
106
  * // [1] <span class="error">Error 2</span>
103
107
  * ```
104
108
  */
105
- export function formatDomGet(data) {
109
+ export function formatDomGet(data, options = {}) {
106
110
  const { nodes } = data;
111
+ const html = (node) => capForDisplay(node.outerHTML ?? '', MAX_VALUE_LENGTH, options.full);
107
112
  if (nodes.length === 1) {
108
113
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
109
- return nodes[0].outerHTML ?? '';
114
+ return html(nodes[0]);
110
115
  }
111
116
  const fmt = new OutputFormatter();
112
117
  nodes.forEach((node, i) => {
113
- fmt.text(`[${i}] ${node.outerHTML}`);
118
+ fmt.text(`[${i}] ${html(node)}`);
114
119
  });
115
120
  return fmt.build();
116
121
  }
@@ -123,9 +128,11 @@ export function formatDomGet(data) {
123
128
  * JSON-quoted. Other values are formatted JSON, and values Chrome only
124
129
  * describes (functions, DOM nodes) their description. The iframe it ran in
125
130
  * (`--frame`) is reported on stderr, so stdout stays the bare value. `--json`
126
- * output is unchanged (the value in `data.result`).
131
+ * output is unchanged (the value in `data.result`). The text is cut to its
132
+ * first {@link MAX_VALUE_LENGTH} characters with a pointer naming `--full`.
127
133
  *
128
134
  * @param data - DOM eval result containing the evaluated value
135
+ * @param options - `full` to print the value whole
129
136
  * @returns The string, or formatted JSON
130
137
  *
131
138
  * @example
@@ -141,7 +148,17 @@ export function formatDomGet(data) {
141
148
  * // }
142
149
  * ```
143
150
  */
144
- export function formatDomEval(data) {
151
+ export function formatDomEval(data, options = {}) {
152
+ return capForDisplay(evalResultText(data), MAX_VALUE_LENGTH, options.full);
153
+ }
154
+ /**
155
+ * An eval result as text: a string as is unless it would read as another
156
+ * value, else formatted JSON.
157
+ *
158
+ * @param data - DOM eval result
159
+ * @returns Text of the value
160
+ */
161
+ function evalResultText(data) {
145
162
  if (data.type === 'undefined')
146
163
  return 'undefined';
147
164
  const { result } = data;
@@ -17,7 +17,7 @@ import { section } from '../formatting.js';
17
17
  export function buildAgentDiscoveryHelp() {
18
18
  const counts = getProtocolCounts();
19
19
  return section('For AI Agents:', [
20
- 'bdg --help --json Machine-readable command schema',
20
+ 'bdg --help --json Commands, flags, exit codes (bdg <cmd> --help --json: details)',
21
21
  `bdg cdp --list List all ${counts.domains} CDP domains`,
22
22
  `bdg cdp --search <term> Search ${counts.methods} CDP methods`,
23
23
  ]);
@@ -212,6 +212,9 @@ function fontParts(text) {
212
212
  }
213
213
  /**
214
214
  * A contrast as words, e.g. `contrast 4.47 fail on #fff (faded: opacity 0.4)`.
215
+ * An approximate one gets no pass/fail level, only the estimate and why
216
+ * (`contrast ≈1 on #fff (approximate: img.hero behind)`): what is behind
217
+ * the text is not a known color.
215
218
  *
216
219
  * @param contrast - Contrast
217
220
  * @returns Words, or undefined
@@ -221,10 +224,9 @@ function contrastText(contrast) {
221
224
  return undefined;
222
225
  return [
223
226
  contrast.approximate
224
- ? `contrast ≈${contrast.ratio} ${contrast.level}`
227
+ ? `contrast ≈${contrast.ratio}`
225
228
  : `contrast ${contrast.ratio} ${contrast.level}`,
226
229
  `on ${contrast.background}`,
227
- contrast.overImage && '(over image)',
228
230
  contrast.opacity !== undefined && `(faded: opacity ${contrast.opacity})`,
229
231
  contrast.approximate && `(approximate: ${contrast.approximate.join(', ')})`,
230
232
  ]
@@ -274,7 +276,7 @@ function fillText(fill) {
274
276
  .join(' ');
275
277
  }
276
278
  /**
277
- * The fill line: backgrounds, opacity and blend mode.
279
+ * The fill line: backgrounds (and that they are clipped to gradient text), opacity and blend mode.
278
280
  *
279
281
  * @param data - Inspect result
280
282
  * @returns Line
@@ -286,6 +288,10 @@ function fillLine(data) {
286
288
  paint &&
287
289
  `stroke ${paint.stroke}${paint.strokeWidth !== undefined ? ` ${paint.strokeWidth}` : ''}`,
288
290
  ...(data.fills ?? []).map(fillText),
291
+ data.text?.gradientFill &&
292
+ !data.text.holder &&
293
+ (data.fills ?? []).length > 0 &&
294
+ 'clipped to the text',
289
295
  data.opacity !== undefined && `opacity ${data.opacity}`,
290
296
  data.blend && `blend ${data.blend}`,
291
297
  ]);
@@ -1,6 +1,14 @@
1
1
  import type { InstalledSkill } from '../../types.js';
2
2
  /**
3
- * Format where the skill was installed, one line per agent.
3
+ * Format the targets the skill was written for, as a failed install lists
4
+ * the ones that succeeded.
5
+ *
6
+ * @param skills - Install results
7
+ * @returns Human-readable lines
8
+ */
9
+ export declare function formatSkillTargets(skills: InstalledSkill[]): string;
10
+ /**
11
+ * Format where the skill was installed, plus what to do next.
4
12
  *
5
13
  * @param data - Install results
6
14
  * @returns Human-readable summary
@@ -1,5 +1,8 @@
1
1
  import { homedir } from 'os';
2
2
  import { OutputFormatter } from '../formatting.js';
3
+ import { skillBackupMessage } from '../messages/commands.js';
4
+ /** Indent of the path column, so a backup line sits under the path it belongs to */
5
+ const PATH_INDENT = ' '.repeat(2 + 6 + 2 + 9 + 2);
3
6
  /**
4
7
  * Shorten a path under the home directory to `~/...`.
5
8
  *
@@ -11,17 +14,40 @@ function tildePath(path) {
11
14
  return path.startsWith(`${home}/`) ? `~${path.slice(home.length)}` : path;
12
15
  }
13
16
  /**
14
- * Format where the skill was installed, one line per agent.
17
+ * Add where the skill was installed, one line per agent, plus where a
18
+ * replaced copy was kept.
19
+ *
20
+ * @param fmt - Formatter to add the lines to
21
+ * @param skills - Install results
22
+ * @returns The formatter
23
+ */
24
+ function addSkillTargets(fmt, skills) {
25
+ fmt.text('bdg skill:');
26
+ for (const skill of skills) {
27
+ fmt.text(` ${skill.target.padEnd(6)} ${skill.status.padEnd(9)} ${tildePath(skill.path)}`);
28
+ if (skill.backup)
29
+ fmt.text(`${PATH_INDENT}${skillBackupMessage(tildePath(skill.backup))}`);
30
+ }
31
+ return fmt;
32
+ }
33
+ /**
34
+ * Format the targets the skill was written for, as a failed install lists
35
+ * the ones that succeeded.
36
+ *
37
+ * @param skills - Install results
38
+ * @returns Human-readable lines
39
+ */
40
+ export function formatSkillTargets(skills) {
41
+ return addSkillTargets(new OutputFormatter(), skills).build();
42
+ }
43
+ /**
44
+ * Format where the skill was installed, plus what to do next.
15
45
  *
16
46
  * @param data - Install results
17
47
  * @returns Human-readable summary
18
48
  */
19
49
  export function formatInstalledSkills(data) {
20
- const fmt = new OutputFormatter().text('bdg skill:');
21
- for (const skill of data.skills) {
22
- fmt.text(` ${skill.target.padEnd(6)} ${skill.status.padEnd(9)} ${tildePath(skill.path)}`);
23
- }
24
- return fmt
50
+ return addSkillTargets(new OutputFormatter(), data.skills)
25
51
  .hints('Next:', [
26
52
  'Start a new agent session to load it (running sessions keep the old list)',
27
53
  'After upgrading bdg, run bdg install-skill again',
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Human-readable output of `bdg dom layout`.
3
3
  */
4
+ import { LAYOUT_ELEMENT_LIMIT } from '../../constants.js';
4
5
  import { indexSourceText } from '../../errors/messages.js';
5
6
  import { OutputFormatter } from '../formatting.js';
6
- import { coverText, indexLayoutHeadline, layoutHeadline, layoutPositionLabel, moreMatchesNote, pageLayoutLine, } from '../messages/commands.js';
7
+ import { coverText, indexLayoutHeadline, layoutHeadline, layoutPositionLabel, maskedText, moreMatchesNote, pageLayoutLine, } from '../messages/commands.js';
7
8
  /** Elements listed in human output (JSON has up to 100) */
8
9
  const LAYOUT_DISPLAY_LIMIT = 20;
9
10
  /**
@@ -26,6 +27,7 @@ export function layoutLine(element, viewport) {
26
27
  element.coveredBy && coverText(element.coveredBy, element.coverTransparent),
27
28
  element.inert && 'inert',
28
29
  element.invisible,
30
+ element.masked && maskedText(element.masked),
29
31
  element.context && element.context !== element.clippedBy && `in ${element.context}`,
30
32
  ]
31
33
  .filter(Boolean)
@@ -47,7 +49,7 @@ export function formatLayout(data) {
47
49
  ? indexLayoutHeadline(indexSourceText(data.indexSource))
48
50
  : layoutHeadline(data.count, data.elements.length + (data.omitted ?? 0), data.selector))
49
51
  .list(shown.map((element) => layoutLine(element, data.page.viewport)))
50
- .list(more > 0 ? [moreMatchesNote(more, data.omitted ? data.elements.length : undefined)] : [])
52
+ .list(more > 0 ? [moreMatchesNote(more, LAYOUT_ELEMENT_LIMIT)] : [])
51
53
  .build();
52
54
  }
53
55
  //# sourceMappingURL=layout.js.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Long values in human output: cut, with a pointer naming `--full`.
3
+ */
4
+ /**
5
+ * A value for human output: its first `maxLength` characters followed by
6
+ * how many more there are, or all of it with `--full`.
7
+ *
8
+ * @param text - Value
9
+ * @param maxLength - Characters printed
10
+ * @param full - `--full`: print it whole
11
+ * @returns Text to print
12
+ */
13
+ export declare function capForDisplay(text: string, maxLength: number, full?: boolean): string;
14
+ //# sourceMappingURL=longValues.d.ts.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Long values in human output: cut, with a pointer naming `--full`.
3
+ */
4
+ import { moreCharsNote } from '../messages/commands.js';
5
+ import { capLength } from '../../utils/strings.js';
6
+ /**
7
+ * A value for human output: its first `maxLength` characters followed by
8
+ * how many more there are, or all of it with `--full`.
9
+ *
10
+ * @param text - Value
11
+ * @param maxLength - Characters printed
12
+ * @param full - `--full`: print it whole
13
+ * @returns Text to print
14
+ */
15
+ export function capForDisplay(text, maxLength, full) {
16
+ if (full)
17
+ return text;
18
+ const capped = capLength(text, maxLength);
19
+ return capped.truncatedFrom === undefined
20
+ ? text
21
+ : `${capped.text}${moreCharsNote(capped.truncatedFrom - capped.text.length)}`;
22
+ }
23
+ //# sourceMappingURL=longValues.js.map
@@ -5,6 +5,7 @@
5
5
  * with support for filtering results display.
6
6
  */
7
7
  import type { NetworkRequest } from '../../types.js';
8
+ import { type NetworkEvictionCounts } from '../messages/networkMessages.js';
8
9
  export interface NetworkListOptions {
9
10
  verbose?: boolean;
10
11
  /** Start of the current page, which the START column counts from ({@link pageStartOf}) */
@@ -13,6 +14,8 @@ export interface NetworkListOptions {
13
14
  totalCount?: number;
14
15
  /** Requests matching the filters, before --last (defaults to totalCount) */
15
16
  filteredCount?: number;
17
+ /** Requests dropped and bodies evicted at the session's capture limits */
18
+ evictions?: NetworkEvictionCounts;
16
19
  }
17
20
  /**
18
21
  * When the current page started loading: the request of its document, in
@@ -41,16 +44,19 @@ export declare function pageStartOf(requests: NetworkRequest[]): PageStart | und
41
44
  export declare function formatStartOffset(request: NetworkRequest, pageStart: PageStart | undefined): string;
42
45
  /**
43
46
  * Rows of the network stream: requests that finished since the last poll,
44
- * with the column header the first time.
47
+ * with the column header the first time (the stream banner is on stderr),
48
+ * after the dropped/evicted note when the counts changed.
45
49
  *
46
50
  * @param requests - Newly finished requests
47
- * @param options - `header` the first time; `verbose` for full URLs; the page start for START
51
+ * @param options - `header` the first time; `verbose` for full URLs; the page start for
52
+ * START; `evictions` only when the session's counts changed since the last poll
48
53
  * @returns Text to print (empty when there is nothing new)
49
54
  */
50
55
  export declare function formatNetworkFollowRows(requests: NetworkRequest[], options?: {
51
56
  header?: boolean;
52
57
  verbose?: boolean;
53
58
  pageStart?: PageStart;
59
+ evictions?: NetworkEvictionCounts;
54
60
  }): string;
55
61
  /**
56
62
  * Format network requests for display.
@@ -7,6 +7,7 @@
7
7
  import { getResourceTypeAbbr } from './preview.js';
8
8
  import { getRequestState } from './requestStatus.js';
9
9
  import { OutputFormatter, truncateUrl } from '../formatting.js';
10
+ import { networkEvictedNote } from '../messages/networkMessages.js';
10
11
  const SIZE_UNITS = ['B', 'KB', 'MB', 'GB'];
11
12
  const SEPARATOR_WIDTH = 80;
12
13
  function formatSize(bytes) {
@@ -154,6 +155,9 @@ function formatNetworkListHuman(requests, options) {
154
155
  const header = buildHeader(requests.length, options.filteredCount ?? totalCount, totalCount);
155
156
  fmt.text(header);
156
157
  fmt.separator('─', SEPARATOR_WIDTH);
158
+ const evictedNote = options.evictions && networkEvictedNote(options.evictions);
159
+ if (evictedNote)
160
+ fmt.text(evictedNote);
157
161
  if (requests.length === 0) {
158
162
  fmt.text('No matching requests found.');
159
163
  return fmt.build();
@@ -170,17 +174,21 @@ function formatNetworkListHuman(requests, options) {
170
174
  const FOLLOW_ID_WIDTH = 14;
171
175
  /**
172
176
  * Rows of the network stream: requests that finished since the last poll,
173
- * with the column header the first time.
177
+ * with the column header the first time (the stream banner is on stderr),
178
+ * after the dropped/evicted note when the counts changed.
174
179
  *
175
180
  * @param requests - Newly finished requests
176
- * @param options - `header` the first time; `verbose` for full URLs; the page start for START
181
+ * @param options - `header` the first time; `verbose` for full URLs; the page start for
182
+ * START; `evictions` only when the session's counts changed since the last poll
177
183
  * @returns Text to print (empty when there is nothing new)
178
184
  */
179
185
  export function formatNetworkFollowRows(requests, options = {}) {
180
186
  const fmt = new OutputFormatter();
181
187
  const widths = columnWidths(requests, FOLLOW_ID_WIDTH);
188
+ const evictedNote = options.evictions && networkEvictedNote(options.evictions);
189
+ if (evictedNote)
190
+ fmt.text(evictedNote);
182
191
  if (options.header) {
183
- fmt.text('Streaming network requests... (Ctrl+C to stop)');
184
192
  fmt.text(formatColumnHeader(widths));
185
193
  fmt.separator('─', SEPARATOR_WIDTH);
186
194
  }
@@ -39,6 +39,8 @@ export interface PreviewOptions {
39
39
  filteredTypes?: string[] | undefined;
40
40
  /** Total network requests before filtering (for showing feedback when no matches). */
41
41
  unfilteredNetworkCount?: number | undefined;
42
+ /** Console message texts whole instead of cut (`--full`). */
43
+ full?: boolean | undefined;
42
44
  }
43
45
  /**
44
46
  * Format preview output (peek command)
@@ -53,11 +55,14 @@ export interface PreviewJsonData {
53
55
  target: BdgOutput['target'];
54
56
  partial?: boolean;
55
57
  totals?: BdgOutput['totals'];
58
+ /** When the page's renderer crashed (epoch ms), while it is not loaded again */
59
+ pageCrashedAt?: number;
56
60
  network?: BdgOutput['data']['network'];
57
61
  console?: BdgOutput['data']['console'];
58
62
  }
59
63
  /**
60
- * Build the JSON payload for a preview, honoring the section and `--last` filters.
64
+ * Build the JSON payload for a preview, honoring the section and `--last`
65
+ * filters; console texts are cut with `truncatedFrom` unless `--full`.
61
66
  *
62
67
  * @param output - Preview output from the daemon
63
68
  * @param options - Preview options (section filters, last N)