browser-debugger-cli 0.13.0 → 0.15.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.
- package/.claude/skills/bdg/SKILL.md +101 -187
- package/README.md +4 -4
- package/dist/commands/cdp.js +1 -0
- package/dist/commands/cleanup.js +3 -0
- package/dist/commands/console.js +5 -1
- package/dist/commands/dom/a11y.d.ts +1 -1
- package/dist/commands/dom/a11y.js +20 -20
- package/dist/commands/dom/eval.d.ts +3 -1
- package/dist/commands/dom/eval.js +8 -5
- package/dist/commands/dom/formInteraction.js +1 -1
- package/dist/commands/dom/get.js +25 -7
- package/dist/commands/dom/helpers/evalResult.d.ts +36 -0
- package/dist/commands/dom/helpers/evalResult.js +59 -0
- package/dist/commands/dom/index.js +7 -2
- package/dist/commands/dom/query.d.ts +2 -1
- package/dist/commands/dom/query.js +5 -3
- package/dist/commands/dom/screenshot.js +1 -0
- package/dist/commands/helpJson.d.ts +1 -1
- package/dist/commands/helpJson.js +4 -4
- package/dist/commands/helpTopic.js +10 -4
- package/dist/commands/network/har.js +18 -14
- package/dist/commands/network/list.js +46 -3
- package/dist/commands/optionBehaviors.d.ts +25 -2
- package/dist/commands/optionBehaviors.js +60 -42
- package/dist/commands/peek.js +3 -0
- package/dist/commands/shared/CommandRunner.js +13 -13
- package/dist/commands/shared/daemonErrorHandler.js +2 -2
- package/dist/commands/shared/dataFetcher.d.ts +4 -2
- package/dist/commands/shared/dataFetcher.js +11 -3
- package/dist/commands/shared/handleValidationError.js +3 -3
- package/dist/commands/shared/optionTypes.d.ts +15 -3
- package/dist/commands/shared/outputFile.d.ts +2 -1
- package/dist/commands/shared/outputFile.js +7 -4
- package/dist/commands/shared/startHelpers.js +3 -3
- package/dist/commands/status.js +3 -1
- package/dist/commands/stop.js +2 -1
- package/dist/connection/chromeIdentity.d.ts +8 -2
- package/dist/connection/chromeIdentity.js +85 -13
- package/dist/connection/launcher/flagsBuilder.d.ts +46 -0
- package/dist/connection/launcher/flagsBuilder.js +107 -23
- package/dist/connection/launcher.d.ts +1 -1
- package/dist/connection/launcher.js +1 -2
- package/dist/constants.d.ts +31 -5
- package/dist/constants.js +37 -5
- package/dist/daemon/SessionController.js +2 -0
- package/dist/daemon/launcher.d.ts +17 -3
- package/dist/daemon/launcher.js +37 -7
- package/dist/daemon/session/Session.d.ts +2 -1
- package/dist/daemon/session/Session.js +10 -2
- package/dist/daemon/session/TelemetryStore.d.ts +7 -0
- package/dist/daemon/session/TelemetryStore.js +6 -0
- package/dist/daemon/session/commandRegistry.js +25 -7
- package/dist/daemon/session/matchedStylesReset.d.ts +26 -0
- package/dist/daemon/session/matchedStylesReset.js +46 -0
- package/dist/daemon/session/plugins.js +1 -0
- package/dist/daemon/session/triggeredRequests.d.ts +0 -5
- package/dist/daemon/session/triggeredRequests.js +13 -7
- package/dist/daemon.js +8742 -8315
- package/dist/errors/messages.d.ts +31 -0
- package/dist/errors/messages.js +96 -6
- package/dist/index.js +1129 -548
- package/dist/ipc/client.d.ts +6 -1
- package/dist/ipc/client.js +11 -2
- package/dist/ipc/protocol/commands.d.ts +8 -0
- package/dist/ipc/protocol/inspectTypes.d.ts +5 -2
- package/dist/ipc/session/types.d.ts +5 -1
- package/dist/ipc/transport/index.d.ts +6 -0
- package/dist/ipc/transport/index.js +16 -1
- package/dist/program.d.ts +14 -0
- package/dist/program.js +53 -0
- package/dist/runtime/dom/elementGeometry.d.ts +23 -0
- package/dist/runtime/dom/elementGeometry.js +17 -15
- package/dist/runtime/dom/elementInfo.d.ts +13 -4
- package/dist/runtime/dom/elementInfo.js +15 -5
- package/dist/runtime/dom/evalHelpers.d.ts +24 -4
- package/dist/runtime/dom/evalHelpers.js +40 -12
- package/dist/runtime/dom/frameScopedConnection.d.ts +7 -0
- package/dist/runtime/dom/frameScopedConnection.js +2 -2
- package/dist/runtime/dom/frames.d.ts +2 -1
- package/dist/runtime/dom/frames.js +3 -1
- package/dist/runtime/dom/inspect.d.ts +17 -3
- package/dist/runtime/dom/inspect.js +40 -26
- package/dist/runtime/dom/inspectModel.d.ts +3 -3
- package/dist/runtime/dom/inspectRules.d.ts +29 -3
- package/dist/runtime/dom/inspectRules.js +205 -11
- package/dist/runtime/dom/layout.d.ts +0 -2
- package/dist/runtime/dom/layout.js +1 -2
- package/dist/runtime/dom/reactEventHelpers.d.ts +4 -1
- package/dist/runtime/dom/reactEventHelpers.js +9 -2
- package/dist/runtime/dom/targetNode.d.ts +10 -6
- package/dist/runtime/dom/targetNode.js +15 -8
- package/dist/runtime/page/emulation.js +6 -5
- package/dist/runtime/page/userAgent.d.ts +86 -2
- package/dist/runtime/page/userAgent.js +154 -33
- package/dist/session/paths.d.ts +38 -3
- package/dist/session/paths.js +154 -7
- package/dist/session/portClaims.d.ts +0 -8
- package/dist/session/portClaims.js +1 -22
- package/dist/session/sessionList.d.ts +5 -1
- package/dist/session/sessionList.js +5 -1
- package/dist/telemetry/a11y.d.ts +15 -1
- package/dist/telemetry/a11y.js +83 -0
- package/dist/telemetry/har/builder.d.ts +12 -1
- package/dist/telemetry/har/builder.js +11 -3
- package/dist/telemetry/har/sanitize.d.ts +24 -0
- package/dist/telemetry/har/sanitize.js +138 -0
- package/dist/telemetry/har/sanitizeBody.d.ts +38 -0
- package/dist/telemetry/har/sanitizeBody.js +168 -0
- package/dist/telemetry/network.d.ts +13 -16
- package/dist/telemetry/network.js +30 -52
- package/dist/telemetry/networkRetention.d.ts +83 -0
- package/dist/telemetry/networkRetention.js +117 -0
- package/dist/types.d.ts +26 -0
- package/dist/ui/OutputBuilder.d.ts +10 -0
- package/dist/ui/OutputBuilder.js +12 -0
- package/dist/ui/formatters/a11y.d.ts +5 -7
- package/dist/ui/formatters/a11y.js +7 -61
- package/dist/ui/formatters/console/chronological.js +4 -4
- package/dist/ui/formatters/console/follow.d.ts +4 -2
- package/dist/ui/formatters/console/follow.js +6 -3
- package/dist/ui/formatters/console/json.d.ts +3 -6
- package/dist/ui/formatters/console/json.js +9 -13
- package/dist/ui/formatters/console/shared.d.ts +17 -2
- package/dist/ui/formatters/console/shared.js +17 -0
- package/dist/ui/formatters/console/summarize.d.ts +2 -2
- package/dist/ui/formatters/console/summarize.js +22 -7
- package/dist/ui/formatters/console.d.ts +1 -1
- package/dist/ui/formatters/console.js +1 -5
- package/dist/ui/formatters/details.js +1 -1
- package/dist/ui/formatters/dom.d.ts +13 -4
- package/dist/ui/formatters/dom.js +25 -7
- package/dist/ui/formatters/layout.js +2 -1
- package/dist/ui/formatters/longValues.d.ts +14 -0
- package/dist/ui/formatters/longValues.js +23 -0
- package/dist/ui/formatters/networkList.d.ts +8 -2
- package/dist/ui/formatters/networkList.js +11 -2
- package/dist/ui/formatters/preview.d.ts +4 -1
- package/dist/ui/formatters/preview.js +55 -13
- package/dist/ui/formatters/sessions.d.ts +3 -2
- package/dist/ui/formatters/sessions.js +10 -3
- package/dist/ui/formatters/status.js +7 -0
- package/dist/ui/formatters/triggeredRequests.js +2 -1
- package/dist/ui/messages/chrome.d.ts +34 -7
- package/dist/ui/messages/chrome.js +81 -15
- package/dist/ui/messages/commands.d.ts +29 -8
- package/dist/ui/messages/commands.js +36 -8
- package/dist/ui/messages/networkMessages.d.ts +50 -0
- package/dist/ui/messages/networkMessages.js +66 -0
- package/dist/ui/messages/session.d.ts +8 -0
- package/dist/ui/messages/session.js +10 -0
- package/dist/utils/atomicFile.d.ts +2 -1
- package/dist/utils/atomicFile.js +5 -2
- package/dist/utils/directories.d.ts +41 -0
- package/dist/utils/directories.js +48 -0
- package/dist/utils/http.d.ts +9 -2
- package/dist/utils/http.js +4 -3
- package/dist/utils/strings.d.ts +19 -0
- package/dist/utils/strings.js +16 -0
- package/package.json +2 -2
|
@@ -65,8 +65,9 @@ const OPTION_BEHAVIORS = {
|
|
|
65
65
|
},
|
|
66
66
|
'get:--full': {
|
|
67
67
|
default: 'Semantic output shows the element text up to 500 characters (whitespace collapsed; close buttons such as "×" and aria-hidden icons left out)',
|
|
68
|
-
whenEnabled: 'Shows all of the element text;
|
|
69
|
-
|
|
68
|
+
whenEnabled: 'Shows all of the element text; with --raw (or --node-id) prints the whole outer HTML instead of its first 20000 characters, and JSON outerHTML is whole too (else cut to 20000 with truncatedFrom, the original length)',
|
|
69
|
+
automaticBehavior: 'Without --full, --raw output cuts each element\'s HTML at 20000 characters and ends it with "… N more chars (use --full)"',
|
|
70
|
+
tokenImpact: 'A page-sized container can add thousands of tokens; dom get body --raw --full on Wikipedia is about 3.4 MB. Target the element you need',
|
|
70
71
|
},
|
|
71
72
|
'get:--all': {
|
|
72
73
|
default: 'Returns first matching element only',
|
|
@@ -78,30 +79,42 @@ const OPTION_BEHAVIORS = {
|
|
|
78
79
|
automaticBehavior: 'Past the last match exits 81; a numeric index argument (a cached query index) past the indexed matches, or from an earlier page, exits 87 (re-run dom query)',
|
|
79
80
|
},
|
|
80
81
|
'query:--limit': {
|
|
81
|
-
default: 'dom query and dom a11y query list the first 50 matches and say how many more there are; --json
|
|
82
|
+
default: 'dom query and dom a11y query list the first 50 matches and say how many more there are; --json lists the first 100 with count (all matches) and omitted (the rest)',
|
|
82
83
|
whenEnabled: 'Lists that many matches (0 = all), in human and JSON output; count is always the total, JSON omitted the rest',
|
|
83
84
|
automaticBehavior: 'Matches are cached for index-based access (bdg dom click 55 works even when 50 are listed): all of them for dom a11y query, the first 1000 (or --limit, if higher) for dom query, which describes only those, so a page with 50000 matches answers in under a second; an element the page and frame trees both report is listed once. Indices work with click, fill, hover, pressKey, scroll, submit, layout, get and listeners, also for elements of a cross-origin iframe of the same site (a consent dialog), whose scripts then run in that frame',
|
|
84
|
-
tokenImpact: 'About one line per match; a page can have
|
|
85
|
+
tokenImpact: 'About one line per match (piped JSON about 160 bytes per dom query match, 230 per a11y match); a page can have thousands of links: on Wikipedia "United States" --limit 0 --json is 1.0 MB (dom query a) and 1.3 MB (dom a11y query role:link), the default 16 KB and 23 KB',
|
|
86
|
+
},
|
|
87
|
+
'tree:--limit': {
|
|
88
|
+
default: 'dom a11y tree lists the first 50 meaningful nodes depth-first, in human and JSON output; JSON count is the whole tree = nodes listed + omitted (cut by --limit/--depth) + skipped (never listed)',
|
|
89
|
+
whenEnabled: 'Lists that many nodes; 0 = all listed nodes (text boxes and empty wrappers are always skipped)',
|
|
90
|
+
automaticBehavior: 'Ignored nodes, text boxes, blank text, text repeating its parent name and nameless layout wrappers (generic, none, presentation, layout tables) are never listed (JSON skipped counts them); their children move up a level. For the raw tree with every node use bdg cdp Accessibility.getFullAXTree --json. JSON nodes carry depth (0 = root) instead of childIds; nodes outside the root (frame content) follow the root tree',
|
|
91
|
+
tokenImpact: 'About 140 bytes per piped JSON node (7 KB by default); the whole tree of a long page is megabytes (Wikipedia "United States": 51k nodes, 20k listed, 2.6 MB with --limit 0 --json), so prefer --depth or dom a11y query "role:<role>"',
|
|
92
|
+
},
|
|
93
|
+
'tree:--depth': {
|
|
94
|
+
default: 'dom a11y tree lists every level (up to --limit nodes)',
|
|
95
|
+
whenEnabled: 'Lists nodes down to that level (0 = root only); deeper nodes are counted in omitted',
|
|
96
|
+
tokenImpact: 'An outline of a page (landmarks, headings) in a few levels',
|
|
85
97
|
},
|
|
86
98
|
'eval:--frame': {
|
|
87
99
|
default: "Evaluates in the page's main frame",
|
|
88
100
|
whenEnabled: "Evaluates in one iframe's main world (its own globals), including cross-origin (out-of-process) iframes; output gains a frame field (its URL)",
|
|
89
101
|
automaticBehavior: 'The value is matched as: a 0-based index (bdg dom frames order: document order of the <iframe> elements, nested ones depth-first, main page not counted), else an exact name/id attribute, else a case-insensitive part of the name, id or URL. Several matches fail with 81 listing them; none fails with 83 listing all frames. Frames are looked up on every call (a reloaded iframe is found again). An index that names another frame than in the last bdg dom frames listing (iframes added, removed or moved, or the page navigated) fails with 87 STALE_CACHE: re-run bdg dom frames or pick the frame by name.',
|
|
90
102
|
},
|
|
91
|
-
'
|
|
92
|
-
default: '
|
|
93
|
-
whenEnabled: '
|
|
94
|
-
|
|
103
|
+
'eval:--full': {
|
|
104
|
+
default: 'Human output prints the first 20000 characters of the value followed by "… N more chars (use --full)". In JSON a string result is cut to 20000 characters with truncatedFrom (the original length); an array result lists its first 100 elements with count (all of them) and omitted; an object or array whose JSON is still over 20000 characters becomes the first 20000 characters of its JSON text (a string; arrays keep count) with truncatedFrom (the length of the JSON text of the copy, which holds at most 1000 entries per list or object): a string result with truncatedFrom while type is object is such a JSON-text start',
|
|
105
|
+
whenEnabled: 'Prints the whole value, byte for byte; objects and arrays are copied with every entry (without --full at most 1000 per list or object)',
|
|
106
|
+
tokenImpact: 'dom eval document.documentElement.outerHTML on Wikipedia is about 3.6 MB with --full; on a page with 20000 elements, [...document.querySelectorAll("*")].map(e => e.outerHTML) --json is 3 MB with --full and 23 KB without; select what you need in the expression instead',
|
|
107
|
+
},
|
|
108
|
+
'console:--full': {
|
|
109
|
+
default: 'Message texts are cut: human output (summary, --list, --follow) at 200 characters followed by "… N more chars (use --full)"; JSON text at 10000 characters with truncatedFrom (the original length)',
|
|
110
|
+
whenEnabled: 'Message texts are printed whole, in human and JSON output',
|
|
111
|
+
tokenImpact: 'A page that logs a large payload or throws a long error can add megabytes; bdg details console <n> shows one message whole',
|
|
95
112
|
},
|
|
96
113
|
'console:--history': {
|
|
97
114
|
default: 'Shows messages from current page load only (most recent navigation)',
|
|
98
115
|
whenEnabled: 'Shows messages from ALL page loads during the session',
|
|
99
116
|
automaticBehavior: 'Page navigations create new "navigation contexts" - default filters to latest context',
|
|
100
117
|
},
|
|
101
|
-
'console:-l': {
|
|
102
|
-
default: 'Smart summary with errors deduplicated and warnings grouped: the newest 50 distinct errors and warnings, with a note for the earlier ones. The session keeps the newest 10000 messages; dropped ones are counted (dropped in JSON)',
|
|
103
|
-
whenEnabled: 'Lists all messages chronologically without deduplication',
|
|
104
|
-
},
|
|
105
118
|
'console:--list': {
|
|
106
119
|
default: 'Smart summary with errors deduplicated and warnings grouped: the newest 50 distinct errors and warnings, with a note for the earlier ones. The session keeps the newest 10000 messages; dropped ones are counted (dropped in JSON)',
|
|
107
120
|
whenEnabled: 'Lists all messages chronologically without deduplication',
|
|
@@ -253,6 +266,7 @@ const OPTION_BEHAVIORS = {
|
|
|
253
266
|
},
|
|
254
267
|
'inspect:--no-hints': {
|
|
255
268
|
default: "Hints at the element's own author declarations that have no effect (flex/grid properties without flex or grid, item properties without a flex or grid parent, offsets on static elements, sizes on inline ones, var() of an unset custom property, form controls in the browser's font), within a 1 s budget; hints none when nothing was found",
|
|
269
|
+
automaticBehavior: "After a hint read times out, later inspects on the same page skip the hints without waiting (hints skipped: this page's stylesheets are slow to read) until a read is fast again, a stylesheet changes or it navigates; --rules and --why still wait up to 5 s. Matched rules that took over 300 ms are reused for up to 5 s, until a command that may change the page or a stylesheet or DOM change",
|
|
256
270
|
whenEnabled: 'Skips the hints and does not read the matched rules',
|
|
257
271
|
},
|
|
258
272
|
'scroll:--down': {
|
|
@@ -293,56 +307,57 @@ const OPTION_BEHAVIORS = {
|
|
|
293
307
|
whenEnabled: 'Quick scan: field names, types, and required status only',
|
|
294
308
|
tokenImpact: 'Reduces output ~50% for initial discovery',
|
|
295
309
|
},
|
|
310
|
+
'peek:--full': {
|
|
311
|
+
default: 'Console message texts are cut: human output at 200 characters (compact output also at 2 lines) followed by "… N more chars (use --full)"; JSON text at 10000 characters with truncatedFrom (the original length)',
|
|
312
|
+
whenEnabled: 'Console message texts are printed whole, in human and JSON output',
|
|
313
|
+
tokenImpact: 'A page that logs a large payload can add megabytes per peek',
|
|
314
|
+
},
|
|
296
315
|
'peek:--type': {
|
|
297
316
|
whenEnabled: 'Filters network requests by CDP resource type. Case-insensitive, comma-separated. Valid: Document, Stylesheet, Image, Media, Font, Script, XHR, Fetch, WebSocket, etc.',
|
|
298
317
|
},
|
|
299
|
-
'peek:-f': {
|
|
300
|
-
default: 'Shows snapshot of current data',
|
|
301
|
-
whenEnabled: 'Continuous monitoring (like tail -f): refreshes every second, or every --interval ms (100-60000). Replaces the deprecated bdg tail',
|
|
302
|
-
automaticBehavior: FOLLOW_BEHAVIOR,
|
|
303
|
-
},
|
|
304
318
|
'peek:--follow': {
|
|
305
319
|
default: 'Shows snapshot of current data',
|
|
306
320
|
whenEnabled: 'Continuous monitoring (like tail -f): refreshes every second, or every --interval ms (100-60000). Replaces the deprecated bdg tail',
|
|
307
321
|
automaticBehavior: FOLLOW_BEHAVIOR,
|
|
308
322
|
},
|
|
309
|
-
'console
|
|
323
|
+
'console:--follow': {
|
|
310
324
|
default: 'Prints the messages logged so far and exits',
|
|
311
325
|
whenEnabled: 'Streams new messages as they come (the last --last at start)',
|
|
312
326
|
automaticBehavior: FOLLOW_BEHAVIOR,
|
|
313
327
|
},
|
|
314
|
-
'list
|
|
328
|
+
'list:--follow': {
|
|
315
329
|
default: 'Lists the requests captured so far and exits',
|
|
316
330
|
whenEnabled: 'Streams requests as they finish',
|
|
317
331
|
automaticBehavior: FOLLOW_BEHAVIOR,
|
|
318
332
|
},
|
|
319
|
-
'
|
|
333
|
+
'har:--include-sensitive': {
|
|
334
|
+
default: 'The HAR is sanitized: values become "[redacted]" for Authorization, Proxy-Authorization, Authentication, Cookie and Set-Cookie headers, X-*key/token/secret/auth headers and headers with an api-key/apikey/token/secret/jwt/subscription-key/session(-id) segment (www-authenticate is kept); every cookie value; query and fragment parameters named like credentials (plus code, sig, key) in the request URL, queryString, redirectURL and Location/Referer headers ("%5Bredacted%5D" in URLs); and password/token/secret/key/session/signature fields of JSON (primitives at any depth under such a name), form-urlencoded (also sniffed when the Content-Type says otherwise) and multipart request bodies. A JSON body too deep to walk becomes "[redacted]" whole. Header, cookie and parameter names, cookie attributes, headersSize and bodySize stay; log.comment and JSON sanitized: true say so',
|
|
335
|
+
whenEnabled: 'Writes every captured value (JSON sanitized: false); human output warns that the file holds credentials',
|
|
336
|
+
automaticBehavior: 'Matching is by name, so it over-redacts: harmless values under credential-looking names (tokenCount: 5, sessionLength) are replaced too, and credentials under other names are kept. Unlike Chrome DevTools, which drops these headers and empties cookies, names are kept so the HAR still shows a request was authenticated. Response bodies and WebSocket messages are not redacted. HAR files are written readable by their owner only (0600). network headers and network getCookies always show real values',
|
|
337
|
+
},
|
|
338
|
+
'peek:--verbose': {
|
|
320
339
|
default: 'Compact output (truncated URLs, no resource types)',
|
|
321
340
|
whenEnabled: 'Verbose output with full URLs and resource types',
|
|
322
341
|
},
|
|
323
|
-
'
|
|
342
|
+
'bdg:--headless': {
|
|
324
343
|
default: 'A window when there is a display: on macOS unless over SSH (SSH_CONNECTION, SSH_TTY) or CI is set; on Linux when DISPLAY or WAYLAND_DISPLAY is set. Servers, containers and CI run headless',
|
|
325
344
|
whenEnabled: 'Chrome runs without a window (pass it when running unattended on a Mac)',
|
|
326
345
|
},
|
|
327
|
-
'
|
|
346
|
+
'bdg:--no-headless': {
|
|
328
347
|
default: 'A window when there is a display: on macOS unless over SSH (SSH_CONNECTION, SSH_TTY) or CI is set; on Linux when DISPLAY or WAYLAND_DISPLAY is set',
|
|
329
348
|
whenEnabled: 'Chrome shows its window even without a detected display (it fails without one)',
|
|
330
349
|
},
|
|
331
|
-
'
|
|
350
|
+
'bdg:--all': {
|
|
332
351
|
default: 'Tracking/analytics requests and console noise are filtered; bodies of binary responses (images, fonts) are not captured',
|
|
333
352
|
whenEnabled: 'Everything is captured, including binary response bodies (base64, flagged by responseBodyBase64, within --max-body-size)',
|
|
334
353
|
tokenImpact: 'details network --json and HAR exports can grow considerably on media-heavy pages',
|
|
335
354
|
},
|
|
336
|
-
'peek:--verbose': {
|
|
337
|
-
default: 'Compact output (truncated URLs, no resource types)',
|
|
338
|
-
whenEnabled: 'Verbose output with full URLs and resource types',
|
|
339
|
-
},
|
|
340
355
|
'bdg:--session': {
|
|
341
356
|
default: 'The default session in ~/.bdg (or $BDG_SESSION_DIR); BDG_SESSION=<name> selects a named session like the flag',
|
|
342
357
|
whenEnabled: 'Uses the named session in ~/.bdg/sessions/<name>/ (or $BDG_SESSION_DIR/sessions/<name>/) with its own daemon, Chrome, profile and port; every command (status, stop, cleanup, ...) acts on that session only',
|
|
343
358
|
automaticBehavior: 'Accepted before or after any subcommand; --session wins over BDG_SESSION. Names are case-insensitive (lower-cased: ALPHA is alpha). Without --port a named session takes the first free port above 9222 not claimed by another running session, and keeps it in port.txt. Names: 1-40 letters, digits, "-" or "_", starting with a letter or digit (exit 81 otherwise, also when the socket path would be too long). Hints and suggestions in its output carry --session <name>',
|
|
344
359
|
},
|
|
345
|
-
'cleanup
|
|
360
|
+
'cleanup:--force': {
|
|
346
361
|
default: 'Refuses to run while a session is active; removes files left by a crashed session',
|
|
347
362
|
whenEnabled: 'Kills the running daemon and its Chrome first (use when a session is stuck)',
|
|
348
363
|
},
|
|
@@ -377,36 +392,39 @@ const OPTION_BEHAVIORS = {
|
|
|
377
392
|
default: 'Chrome launched by bdg is always closed on stop; an attached Chrome (--chrome-ws-url) is left running',
|
|
378
393
|
whenEnabled: 'No additional effect; kept for compatibility',
|
|
379
394
|
},
|
|
380
|
-
'status:-v': {
|
|
381
|
-
default: 'Basic session status (daemon running, session active, URL)',
|
|
382
|
-
whenEnabled: 'Includes Chrome diagnostics and CDP connection details',
|
|
383
|
-
},
|
|
384
395
|
'status:--verbose': {
|
|
385
396
|
default: 'Basic session status (daemon running, session active, URL)',
|
|
386
397
|
whenEnabled: 'Includes Chrome diagnostics and CDP connection details',
|
|
387
398
|
},
|
|
388
399
|
};
|
|
389
400
|
/**
|
|
390
|
-
* Build behavior registry key from command and
|
|
401
|
+
* Build behavior registry key from command and option: the command's own
|
|
402
|
+
* name (`bdg` for the root) and the option's long flag, or its short flag
|
|
403
|
+
* when it has no long one.
|
|
391
404
|
*
|
|
392
405
|
* @param commandName - Command name (e.g., "screenshot")
|
|
393
|
-
* @param
|
|
406
|
+
* @param option - Commander option
|
|
394
407
|
* @returns Registry key
|
|
395
408
|
*/
|
|
396
|
-
function
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
409
|
+
export function behaviorKey(commandName, option) {
|
|
410
|
+
return `${commandName}:${option.long ?? option.short ?? option.flags}`;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Every key in the behavior registry.
|
|
414
|
+
*
|
|
415
|
+
* @returns Registry keys
|
|
416
|
+
*/
|
|
417
|
+
export function listBehaviorKeys() {
|
|
418
|
+
return Object.keys(OPTION_BEHAVIORS);
|
|
400
419
|
}
|
|
401
420
|
/**
|
|
402
421
|
* Look up behavioral metadata for an option.
|
|
403
422
|
*
|
|
404
423
|
* @param commandName - Name of the command containing the option
|
|
405
|
-
* @param
|
|
424
|
+
* @param option - Commander option
|
|
406
425
|
* @returns Behavioral metadata if registered, undefined otherwise
|
|
407
426
|
*/
|
|
408
|
-
export function getOptionBehavior(commandName,
|
|
409
|
-
|
|
410
|
-
return OPTION_BEHAVIORS[key];
|
|
427
|
+
export function getOptionBehavior(commandName, option) {
|
|
428
|
+
return OPTION_BEHAVIORS[behaviorKey(commandName, option)];
|
|
411
429
|
}
|
|
412
430
|
//# sourceMappingURL=optionBehaviors.js.map
|
package/dist/commands/peek.js
CHANGED
|
@@ -8,6 +8,7 @@ import { fetchPreviewOutput, createErrorResult, } from './shared/dataFetcher.js'
|
|
|
8
8
|
import { followFetchFailure, setupFollowMode, } from './shared/followMode.js';
|
|
9
9
|
import { handleValidationError } from './shared/handleValidationError.js';
|
|
10
10
|
import { MAX_LAST_ITEMS, positiveIntRule, resourceTypeRule } from './shared/validation.js';
|
|
11
|
+
import { MAX_CONSOLE_JSON_TEXT_LENGTH, MAX_CONSOLE_TEXT_LENGTH } from '../constants.js';
|
|
11
12
|
import { CommandError } from '../errors/index.js';
|
|
12
13
|
import { intervalWithoutFollowError } from '../errors/messages.js';
|
|
13
14
|
import { filterByResourceType } from '../telemetry/filters.js';
|
|
@@ -137,6 +138,7 @@ function previewDisplayOptions(options, lastN) {
|
|
|
137
138
|
last: lastN,
|
|
138
139
|
verbose: options.verbose,
|
|
139
140
|
follow: options.follow,
|
|
141
|
+
full: options.full,
|
|
140
142
|
};
|
|
141
143
|
}
|
|
142
144
|
/**
|
|
@@ -162,6 +164,7 @@ export function registerPeekCommand(program) {
|
|
|
162
164
|
.option('--interval <ms>', 'Refresh interval of --follow in ms, 100-60000 (default: 1000)')
|
|
163
165
|
.option('--last <count>', 'Show last N items, 0 for all', '10')
|
|
164
166
|
.option('--type <types>', 'Filter network requests by resource type (comma-separated: Document,XHR,Fetch,etc.)')
|
|
167
|
+
.option('--full', `Print console message texts whole (default: the first ${MAX_CONSOLE_TEXT_LENGTH} characters, ${MAX_CONSOLE_JSON_TEXT_LENGTH} in JSON)`, false)
|
|
165
168
|
.action(async (options) => {
|
|
166
169
|
showBothSectionsWhenBothRequested(options);
|
|
167
170
|
if (options.network && !options.json) {
|
|
@@ -2,7 +2,7 @@ import { getQuickIPCRequestTimeout } from '../../constants.js';
|
|
|
2
2
|
import { CommandError, isDaemonConnectionError } from '../../errors/index.js';
|
|
3
3
|
import { daemonNotRunningError, unknownError, genericError, commandTimedOutError, sessionNotRespondingError, sessionEndedDuringCommandError, } from '../../errors/messages.js';
|
|
4
4
|
import { IPCEarlyCloseError, IPCTimeoutError } from '../../ipc/transport/IPCError.js';
|
|
5
|
-
import { OutputBuilder, buildSuccessResponse } from '../../ui/OutputBuilder.js';
|
|
5
|
+
import { OutputBuilder, buildSuccessResponse, stringifyEnvelope } from '../../ui/OutputBuilder.js';
|
|
6
6
|
import { escapeControlChars } from '../../ui/formatting.js';
|
|
7
7
|
import { noActiveSessionMessage, startSessionSuggestion } from '../../ui/messages/sessionCommand.js';
|
|
8
8
|
import { getErrorExitCode, getErrorMessage } from '../../utils/errors.js';
|
|
@@ -36,7 +36,7 @@ export function noActiveSessionError() {
|
|
|
36
36
|
export async function runJsonCommand(fn) {
|
|
37
37
|
try {
|
|
38
38
|
const data = await fn();
|
|
39
|
-
console.log(
|
|
39
|
+
console.log(stringifyEnvelope(buildSuccessResponse(data)));
|
|
40
40
|
process.exit(EXIT_CODES.SUCCESS);
|
|
41
41
|
}
|
|
42
42
|
catch (caught) {
|
|
@@ -49,10 +49,10 @@ export async function runJsonCommand(fn) {
|
|
|
49
49
|
const suggestion = error instanceof CommandError && typeof error.metadata['suggestion'] === 'string'
|
|
50
50
|
? error.metadata['suggestion']
|
|
51
51
|
: undefined;
|
|
52
|
-
console.log(
|
|
52
|
+
console.log(stringifyEnvelope(OutputBuilder.buildJsonError(getErrorMessage(error), {
|
|
53
53
|
exitCode,
|
|
54
54
|
...(suggestion && { suggestion }),
|
|
55
|
-
})
|
|
55
|
+
})));
|
|
56
56
|
process.exit(exitCode);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -112,10 +112,10 @@ export async function runCommand(handler, options, formatter) {
|
|
|
112
112
|
if (!result.success) {
|
|
113
113
|
const exitCode = result.exitCode ?? EXIT_CODES.UNHANDLED_EXCEPTION;
|
|
114
114
|
if (options.json) {
|
|
115
|
-
console.log(
|
|
115
|
+
console.log(stringifyEnvelope(OutputBuilder.buildJsonError(result.error ?? 'Unknown error', {
|
|
116
116
|
...result.errorContext,
|
|
117
117
|
exitCode,
|
|
118
|
-
})
|
|
118
|
+
})));
|
|
119
119
|
}
|
|
120
120
|
else {
|
|
121
121
|
console.error(result.error ? genericError(result.error) : unknownError());
|
|
@@ -133,14 +133,14 @@ export async function runCommand(handler, options, formatter) {
|
|
|
133
133
|
console.error(escapeControlChars(result.hint));
|
|
134
134
|
}
|
|
135
135
|
if (options.json) {
|
|
136
|
-
console.log(
|
|
136
|
+
console.log(stringifyEnvelope(buildSuccessResponse(result.data)));
|
|
137
137
|
}
|
|
138
138
|
else if (formatter) {
|
|
139
139
|
const formattedOutput = formatter(result.data);
|
|
140
140
|
console.log(escapeControlChars(formattedOutput));
|
|
141
141
|
}
|
|
142
142
|
else {
|
|
143
|
-
console.log(
|
|
143
|
+
console.log(stringifyEnvelope(buildSuccessResponse(result.data)));
|
|
144
144
|
}
|
|
145
145
|
process.exit(EXIT_CODES.SUCCESS);
|
|
146
146
|
}
|
|
@@ -152,10 +152,10 @@ export async function runCommand(handler, options, formatter) {
|
|
|
152
152
|
: caught;
|
|
153
153
|
if (error instanceof CommandError) {
|
|
154
154
|
if (options.json) {
|
|
155
|
-
console.log(
|
|
155
|
+
console.log(stringifyEnvelope(OutputBuilder.buildJsonError(error.message, {
|
|
156
156
|
...error.metadata,
|
|
157
157
|
exitCode: error.exitCode,
|
|
158
|
-
})
|
|
158
|
+
})));
|
|
159
159
|
}
|
|
160
160
|
else {
|
|
161
161
|
console.error(genericError(error.message));
|
|
@@ -168,10 +168,10 @@ export async function runCommand(handler, options, formatter) {
|
|
|
168
168
|
const errorMessage = getErrorMessage(error);
|
|
169
169
|
if (isDaemonConnectionError(error)) {
|
|
170
170
|
if (options.json) {
|
|
171
|
-
console.log(
|
|
171
|
+
console.log(stringifyEnvelope(OutputBuilder.buildJsonError(noActiveSessionMessage(), {
|
|
172
172
|
suggestion: startSessionSuggestion(),
|
|
173
173
|
exitCode: EXIT_CODES.RESOURCE_NOT_FOUND,
|
|
174
|
-
})
|
|
174
|
+
})));
|
|
175
175
|
}
|
|
176
176
|
else {
|
|
177
177
|
console.error(daemonNotRunningError());
|
|
@@ -180,7 +180,7 @@ export async function runCommand(handler, options, formatter) {
|
|
|
180
180
|
}
|
|
181
181
|
const exitCode = getErrorExitCode(error, EXIT_CODES.UNHANDLED_EXCEPTION);
|
|
182
182
|
if (options.json) {
|
|
183
|
-
console.log(
|
|
183
|
+
console.log(stringifyEnvelope(OutputBuilder.buildJsonError(errorMessage, { exitCode })));
|
|
184
184
|
}
|
|
185
185
|
else {
|
|
186
186
|
console.error(genericError(errorMessage));
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { sessionUnavailableSuggestion } from '../../errors/messages.js';
|
|
5
5
|
import { genericError } from '../../errors/messages.js';
|
|
6
|
-
import { OutputBuilder } from '../../ui/OutputBuilder.js';
|
|
6
|
+
import { OutputBuilder, stringifyEnvelope } from '../../ui/OutputBuilder.js';
|
|
7
7
|
import { connectionLostRetryMessage, connectionLostStopHintMessage, followedSessionEndedMessage, } from '../../ui/messages/preview.js';
|
|
8
8
|
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
9
9
|
/** Follow-mode state: whether a session ever answered, and whether its loss was reported */
|
|
@@ -42,7 +42,7 @@ export function handleDaemonConnectionError(error, options) {
|
|
|
42
42
|
exitCode,
|
|
43
43
|
...(suggestion && { suggestion }),
|
|
44
44
|
});
|
|
45
|
-
console.log(follow ? JSON.stringify(envelope) :
|
|
45
|
+
console.log(follow ? JSON.stringify(envelope) : stringifyEnvelope(envelope));
|
|
46
46
|
}
|
|
47
47
|
else {
|
|
48
48
|
console.error(genericError(message));
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { PeekSection } from '../../ipc/protocol/commands.js';
|
|
5
5
|
import type { BdgOutput, ConsoleMessage, NetworkRequest } from '../../types.js';
|
|
6
|
+
import type { NetworkEvictionCounts } from '../../ui/messages/networkMessages.js';
|
|
6
7
|
export type FetchSuccess<T> = {
|
|
7
8
|
success: true;
|
|
8
9
|
data: T;
|
|
@@ -47,12 +48,13 @@ export declare function fetchPreviewData(query?: PreviewQuery): Promise<FetchRes
|
|
|
47
48
|
* Fetch all captured network requests from daemon.
|
|
48
49
|
*
|
|
49
50
|
* @param withHeaders - Include request/response headers (needed by header filters)
|
|
50
|
-
* @returns Requests,
|
|
51
|
-
*
|
|
51
|
+
* @returns Requests, when the page crashed (while it is not loaded again)
|
|
52
|
+
* and what the session let go at its capture limits, or a fetch error
|
|
52
53
|
*/
|
|
53
54
|
export declare function fetchNetworkRequests(withHeaders?: boolean): Promise<FetchResult<{
|
|
54
55
|
requests: NetworkRequest[];
|
|
55
56
|
pageCrashedAt: number | undefined;
|
|
57
|
+
evictions: NetworkEvictionCounts;
|
|
56
58
|
}>>;
|
|
57
59
|
/**
|
|
58
60
|
* Fetch all console messages from daemon.
|
|
@@ -90,16 +90,24 @@ export async function fetchPreviewData(query = {}) {
|
|
|
90
90
|
* Fetch all captured network requests from daemon.
|
|
91
91
|
*
|
|
92
92
|
* @param withHeaders - Include request/response headers (needed by header filters)
|
|
93
|
-
* @returns Requests,
|
|
94
|
-
*
|
|
93
|
+
* @returns Requests, when the page crashed (while it is not loaded again)
|
|
94
|
+
* and what the session let go at its capture limits, or a fetch error
|
|
95
95
|
*/
|
|
96
96
|
export async function fetchNetworkRequests(withHeaders = false) {
|
|
97
97
|
const result = await fetchPreviewData({ lastN: 0, only: 'network', withHeaders });
|
|
98
98
|
if (!result.success)
|
|
99
99
|
return result;
|
|
100
|
+
const { totals, pageCrashedAt } = result.data.output;
|
|
100
101
|
return {
|
|
101
102
|
success: true,
|
|
102
|
-
data: {
|
|
103
|
+
data: {
|
|
104
|
+
requests: result.data.network,
|
|
105
|
+
pageCrashedAt,
|
|
106
|
+
evictions: {
|
|
107
|
+
requestsDropped: totals?.networkDropped ?? 0,
|
|
108
|
+
bodiesEvicted: totals?.networkBodiesEvicted ?? 0,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
103
111
|
};
|
|
104
112
|
}
|
|
105
113
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CommandError } from '../../errors/index.js';
|
|
2
2
|
import { genericError } from '../../errors/messages.js';
|
|
3
|
-
import { OutputBuilder } from '../../ui/OutputBuilder.js';
|
|
3
|
+
import { OutputBuilder, stringifyEnvelope } from '../../ui/OutputBuilder.js';
|
|
4
4
|
import { escapeControlChars } from '../../ui/formatting.js';
|
|
5
5
|
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
6
6
|
/**
|
|
@@ -24,7 +24,7 @@ export function handleValidationError(error, json) {
|
|
|
24
24
|
if (error.metadata.suggestion) {
|
|
25
25
|
errorOptions.suggestion = error.metadata.suggestion;
|
|
26
26
|
}
|
|
27
|
-
console.log(
|
|
27
|
+
console.log(stringifyEnvelope(OutputBuilder.buildJsonError(error.message, errorOptions)));
|
|
28
28
|
}
|
|
29
29
|
else {
|
|
30
30
|
console.error(genericError(error.message));
|
|
@@ -38,7 +38,7 @@ export function handleValidationError(error, json) {
|
|
|
38
38
|
const envelope = OutputBuilder.buildJsonError(message, {
|
|
39
39
|
exitCode: EXIT_CODES.INVALID_ARGUMENTS,
|
|
40
40
|
});
|
|
41
|
-
console.log(
|
|
41
|
+
console.log(stringifyEnvelope(envelope));
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
44
44
|
console.error(genericError(message));
|
|
@@ -143,12 +143,12 @@ export type DetailsCommandOptions = BaseOptions & {
|
|
|
143
143
|
};
|
|
144
144
|
/** Options for DOM query command */
|
|
145
145
|
export type DomQueryCommandOptions = BaseOptions & {
|
|
146
|
-
/** Matches listed (0 = all); default 50, or
|
|
146
|
+
/** Matches listed (0 = all); default 50, or 100 with --json */
|
|
147
147
|
limit?: number;
|
|
148
148
|
};
|
|
149
149
|
/** Options for DOM get command */
|
|
150
150
|
export type DomGetCommandOptions = BaseOptions & RawOptions & SelectionOptions & {
|
|
151
|
-
/** All of the element's text
|
|
151
|
+
/** All of the element's text (semantic output) or HTML (`--raw`), instead of its start */
|
|
152
152
|
full?: boolean;
|
|
153
153
|
/** Which match of the selector (0-based); `--nth` is its alias */
|
|
154
154
|
index?: number;
|
|
@@ -159,6 +159,8 @@ export type DomScreenshotCommandOptions = BaseOptions & ScreenshotOptions;
|
|
|
159
159
|
export interface DomEvalCommandOptions extends BaseOptions {
|
|
160
160
|
/** Iframe to evaluate in: index, name/id attribute, or part of the name, id or URL */
|
|
161
161
|
frame?: string;
|
|
162
|
+
/** The whole value instead of its first 20000 characters */
|
|
163
|
+
full?: boolean;
|
|
162
164
|
}
|
|
163
165
|
/** Options for DOM frames command */
|
|
164
166
|
export type DomFramesCommandOptions = BaseOptions;
|
|
@@ -276,7 +278,12 @@ export interface WaitCommandOptions extends BaseOptions {
|
|
|
276
278
|
timeout: number;
|
|
277
279
|
}
|
|
278
280
|
/** Options for A11y tree command */
|
|
279
|
-
export
|
|
281
|
+
export interface A11yTreeCommandOptions extends BaseOptions {
|
|
282
|
+
/** Nodes to list (0 = all); default 50, also with --json */
|
|
283
|
+
limit?: number;
|
|
284
|
+
/** Levels below the root to list (0 = root only) */
|
|
285
|
+
depth?: number;
|
|
286
|
+
}
|
|
280
287
|
/** Options for A11y query command */
|
|
281
288
|
export interface A11yQueryCommandOptions extends BaseOptions {
|
|
282
289
|
/** Matches to list (0 = all) */
|
|
@@ -293,6 +300,7 @@ export type NetworkCookiesCommandOptions = BaseOptions & {
|
|
|
293
300
|
/** Options for network HAR command */
|
|
294
301
|
export type NetworkHarCommandOptions = BaseOptions & {
|
|
295
302
|
outputFile?: string;
|
|
303
|
+
includeSensitive?: boolean;
|
|
296
304
|
};
|
|
297
305
|
/** Options for network headers command */
|
|
298
306
|
export type NetworkHeadersCommandOptions = BaseOptions & {
|
|
@@ -354,6 +362,8 @@ export interface ConsoleCommandOptions extends BaseOptions {
|
|
|
354
362
|
history?: boolean;
|
|
355
363
|
/** Filter by message level (error, warning, info, debug) */
|
|
356
364
|
level?: ConsoleLevel;
|
|
365
|
+
/** Message texts whole instead of cut */
|
|
366
|
+
full?: boolean;
|
|
357
367
|
}
|
|
358
368
|
/**
|
|
359
369
|
* Options for preview display.
|
|
@@ -380,6 +390,8 @@ export interface PeekCommandOptions extends BaseOptions, PreviewDisplayOptions {
|
|
|
380
390
|
type?: string;
|
|
381
391
|
/** Refresh interval of --follow in ms (string from CLI, default: 1000) */
|
|
382
392
|
interval?: string;
|
|
393
|
+
/** Console message texts whole instead of cut */
|
|
394
|
+
full?: boolean;
|
|
383
395
|
}
|
|
384
396
|
/**
|
|
385
397
|
* Options for tail command.
|
|
@@ -26,8 +26,9 @@ export declare function assertFilePath(filePath: string, extension?: string): vo
|
|
|
26
26
|
* @param filePath - Path the user gave
|
|
27
27
|
* @param data - File contents
|
|
28
28
|
* @param extension - Extension of the file kind, for examples in errors
|
|
29
|
+
* @param mode - File permissions of a text file (default: 0666 less the umask)
|
|
29
30
|
* @returns Absolute path written
|
|
30
31
|
* @throws CommandError naming the path when it cannot be written
|
|
31
32
|
*/
|
|
32
|
-
export declare function writeOutputFile(filePath: string, data: string | Buffer, extension?: string): Promise<string>;
|
|
33
|
+
export declare function writeOutputFile(filePath: string, data: string | Buffer, extension?: string, mode?: number): Promise<string>;
|
|
33
34
|
//# sourceMappingURL=outputFile.d.ts.map
|
|
@@ -62,18 +62,21 @@ export function assertFilePath(filePath, extension) {
|
|
|
62
62
|
* @param filePath - Path the user gave
|
|
63
63
|
* @param data - File contents
|
|
64
64
|
* @param extension - Extension of the file kind, for examples in errors
|
|
65
|
+
* @param mode - File permissions of a text file (default: 0666 less the umask)
|
|
65
66
|
* @returns Absolute path written
|
|
66
67
|
* @throws CommandError naming the path when it cannot be written
|
|
67
68
|
*/
|
|
68
|
-
export async function writeOutputFile(filePath, data, extension) {
|
|
69
|
+
export async function writeOutputFile(filePath, data, extension, mode) {
|
|
69
70
|
assertFilePath(filePath, extension);
|
|
70
71
|
const absolutePath = path.resolve(filePath);
|
|
71
72
|
try {
|
|
72
73
|
makeDirectory(path.dirname(absolutePath));
|
|
73
|
-
if (typeof data === 'string')
|
|
74
|
-
await AtomicFileWriter.writeAsync(absolutePath, data);
|
|
75
|
-
|
|
74
|
+
if (typeof data === 'string') {
|
|
75
|
+
await AtomicFileWriter.writeAsync(absolutePath, data, mode === undefined ? {} : { mode });
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
76
78
|
await AtomicFileWriter.writeBufferAsync(absolutePath, data);
|
|
79
|
+
}
|
|
77
80
|
}
|
|
78
81
|
catch (error) {
|
|
79
82
|
throw outputPathError(filePath, error, extension);
|
|
@@ -14,7 +14,7 @@ import { IPCErrorCode, } from '../../ipc/index.js';
|
|
|
14
14
|
import { IPCTimeoutError } from '../../ipc/transport/index.js';
|
|
15
15
|
import { isConnectionError } from '../../ipc/utils/errors.js';
|
|
16
16
|
import { getSessionName } from '../../session/paths.js';
|
|
17
|
-
import { OutputBuilder, buildSuccessResponse } from '../../ui/OutputBuilder.js';
|
|
17
|
+
import { OutputBuilder, buildSuccessResponse, stringifyEnvelope } from '../../ui/OutputBuilder.js';
|
|
18
18
|
import { escapeControlChars, joinLines } from '../../ui/formatting.js';
|
|
19
19
|
import { createLogger } from '../../ui/logging/index.js';
|
|
20
20
|
import { daemonStillExitingHint, daemonStillExitingSuggestion, startNotices, } from '../../ui/messages/session.js';
|
|
@@ -318,7 +318,7 @@ function reportStartOutcome(outcome, options) {
|
|
|
318
318
|
exitCode: outcome.exitCode,
|
|
319
319
|
...outcome.details,
|
|
320
320
|
});
|
|
321
|
-
console.log(
|
|
321
|
+
console.log(stringifyEnvelope(envelope));
|
|
322
322
|
}
|
|
323
323
|
else {
|
|
324
324
|
console.error(escapeControlChars(outcome.human));
|
|
@@ -340,7 +340,7 @@ function reportStartOutcome(outcome, options) {
|
|
|
340
340
|
daemonPid: data.daemonPid,
|
|
341
341
|
...(autoStopAt && { autoStopAt: autoStopAt.toISOString() }),
|
|
342
342
|
};
|
|
343
|
-
console.log(
|
|
343
|
+
console.log(stringifyEnvelope(buildSuccessResponse(result)));
|
|
344
344
|
}
|
|
345
345
|
else {
|
|
346
346
|
const page = {
|
package/dist/commands/status.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { runCommand } from './shared/CommandRunner.js';
|
|
2
|
-
import { isDaemonConnectionError } from '../errors/index.js';
|
|
2
|
+
import { CommandError, isDaemonConnectionError } from '../errors/index.js';
|
|
3
3
|
import { invalidResponseError, sessionNotRespondingError } from '../errors/messages.js';
|
|
4
4
|
import { getStatus } from '../ipc/client.js';
|
|
5
5
|
import { IPCTimeoutError } from '../ipc/transport/IPCError.js';
|
|
@@ -134,6 +134,8 @@ export function registerStatusCommand(program) {
|
|
|
134
134
|
return { success: true, data: withSessionName(jsonOutput) };
|
|
135
135
|
}
|
|
136
136
|
catch (error) {
|
|
137
|
+
if (error instanceof CommandError)
|
|
138
|
+
throw error;
|
|
137
139
|
const errorMessage = getErrorMessage(error);
|
|
138
140
|
if (error instanceof IPCTimeoutError) {
|
|
139
141
|
const err = sessionNotRespondingError(error.timeoutMs / 1000);
|
package/dist/commands/stop.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { runCommand } from './shared/CommandRunner.js';
|
|
2
2
|
import { jsonOption } from './shared/commonOptions.js';
|
|
3
|
+
import { CommandError } from '../errors/index.js';
|
|
3
4
|
import { stopSession } from '../ipc/client.js';
|
|
4
5
|
import { IPCErrorCode } from '../ipc/index.js';
|
|
5
6
|
import { IPCTimeoutError } from '../ipc/transport/index.js';
|
|
@@ -97,7 +98,7 @@ export function registerStopCommand(program) {
|
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
catch (error) {
|
|
100
|
-
if (error instanceof IPCTimeoutError)
|
|
101
|
+
if (error instanceof IPCTimeoutError || error instanceof CommandError)
|
|
101
102
|
throw error;
|
|
102
103
|
const errorMessage = getErrorMessage(error);
|
|
103
104
|
if (isDaemonNotRunningError(errorMessage)) {
|
|
@@ -49,12 +49,18 @@ export declare function waitForDevToolsEndpoint(logs: StartupLogs, isRunning: ()
|
|
|
49
49
|
* Check that the Chrome answering on 127.0.0.1:<port> is the one just
|
|
50
50
|
* launched, so bdg never drives another session's browser.
|
|
51
51
|
*
|
|
52
|
+
* A Chrome that announced 127.0.0.1:<port> but does not answer yet (a slow
|
|
53
|
+
* start, its `/json/version` request timing out) is asked again until the
|
|
54
|
+
* deadline; only an answer from something else is a port conflict. A Chrome
|
|
55
|
+
* that fell back to [::1] is asked once: 127.0.0.1 is held by something else.
|
|
56
|
+
*
|
|
52
57
|
* @param options - Chrome's log positions from before the launch, requested
|
|
53
58
|
* port (free on 127.0.0.1 and ::1 right before the launch), Chrome's PID and
|
|
54
|
-
* longest wait for its announcement
|
|
59
|
+
* longest wait for its announcement and its answer
|
|
55
60
|
* @throws ChromeLaunchError: CHROME_DIED_AFTER_LAUNCH if Chrome exits first;
|
|
56
61
|
* PORT_IN_USE if another browser or process answers on the port;
|
|
57
|
-
* CHROME_LAUNCH_FAILED if Chrome announced nothing and nothing answers
|
|
62
|
+
* CHROME_LAUNCH_FAILED if Chrome announced nothing and nothing answers, or
|
|
63
|
+
* announced the port but did not answer on it in time
|
|
58
64
|
*/
|
|
59
65
|
export declare function verifyLaunchedChrome(options: {
|
|
60
66
|
logs: StartupLogs;
|