@browserbridge/bbx 1.8.0 → 1.9.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/PRIVACY.md +29 -3
- package/README.md +10 -3
- package/SECURITY.md +12 -0
- package/package.json +7 -1
- package/packages/agent-client/src/cli-args.js +35 -0
- package/packages/agent-client/src/cli-batch.js +121 -58
- package/packages/agent-client/src/cli-output.js +8 -1
- package/packages/agent-client/src/cli.js +227 -19
- package/packages/agent-client/src/client.js +156 -3
- package/packages/agent-client/src/command-registry.js +8 -2
- package/packages/agent-client/src/config.js +195 -0
- package/packages/agent-client/src/npm-self-update.js +305 -0
- package/packages/agent-client/src/remotes.js +4 -2
- package/packages/agent-client/src/runtime.js +97 -5
- package/packages/agent-client/src/types.ts +38 -0
- package/packages/mcp-server/src/handlers-capture.js +29 -2
- package/packages/mcp-server/src/handlers-dom.js +54 -3
- package/packages/mcp-server/src/handlers-page.js +180 -60
- package/packages/mcp-server/src/handlers-utils.js +35 -4
- package/packages/mcp-server/src/handlers.js +10 -3
- package/packages/mcp-server/src/server.js +75 -6
- package/packages/native-host/src/artifact-store.js +353 -0
- package/packages/native-host/src/config.js +9 -1
- package/packages/native-host/src/daemon-logger.js +3 -1
- package/packages/native-host/src/daemon.js +543 -27
- package/packages/native-host/src/native-host.js +25 -2
- package/packages/protocol/src/capability-values.js +2 -0
- package/packages/protocol/src/defaults.js +28 -0
- package/packages/protocol/src/errors.js +48 -5
- package/packages/protocol/src/incidental-sanitizer.js +197 -0
- package/packages/protocol/src/index.js +2 -0
- package/packages/protocol/src/protocol.js +316 -6
- package/packages/protocol/src/recovery-telemetry.js +302 -0
- package/packages/protocol/src/registry.js +143 -6
- package/packages/protocol/src/summary.js +116 -25
- package/packages/protocol/src/types.ts +489 -4
- package/skills/browser-bridge/SKILL.md +22 -8
- package/skills/browser-bridge/references/protocol.md +117 -13
- package/skills/browser-bridge/references/token-efficiency.md +17 -7
|
@@ -29,7 +29,8 @@ export type Capability =
|
|
|
29
29
|
| 'tabs.manage'
|
|
30
30
|
| 'performance.read'
|
|
31
31
|
| 'network.read'
|
|
32
|
-
| 'network.intercept'
|
|
32
|
+
| 'network.intercept'
|
|
33
|
+
| 'sensitive.read';
|
|
33
34
|
|
|
34
35
|
export type ErrorCode =
|
|
35
36
|
| 'ACCESS_DENIED'
|
|
@@ -45,7 +46,15 @@ export type ErrorCode =
|
|
|
45
46
|
| 'DIALOG_NOT_OPEN'
|
|
46
47
|
| 'DIALOG_ACTION_CONFLICT'
|
|
47
48
|
| 'RESULT_TRUNCATED'
|
|
48
|
-
| '
|
|
49
|
+
| 'RESULT_TOO_LARGE'
|
|
50
|
+
| 'SENSITIVE_TARGET_NOT_FOUND'
|
|
51
|
+
| 'CONTENT_SCRIPT_UNAVAILABLE'
|
|
52
|
+
| 'ARTIFACT_NOT_FOUND'
|
|
53
|
+
| 'ARTIFACT_QUOTA_EXCEEDED'
|
|
54
|
+
| 'ARTIFACT_TRANSFER_INVALID'
|
|
55
|
+
| 'DOM_BASELINE_NOT_FOUND'
|
|
56
|
+
| 'DOM_BASELINE_INVALIDATED'
|
|
57
|
+
| 'DOM_BASELINE_QUOTA_EXCEEDED'
|
|
49
58
|
| 'INTERNAL_ERROR'
|
|
50
59
|
| 'INVALID_REQUEST'
|
|
51
60
|
| 'NATIVE_HOST_UNAVAILABLE'
|
|
@@ -67,9 +76,11 @@ export type BridgeMethod =
|
|
|
67
76
|
| 'page.handle_dialog'
|
|
68
77
|
| 'page.wait_for_load_state'
|
|
69
78
|
| 'page.get_storage'
|
|
79
|
+
| 'sensitive.read'
|
|
70
80
|
| 'page.get_text'
|
|
71
81
|
| 'page.extract_content'
|
|
72
82
|
| 'page.get_network'
|
|
83
|
+
| 'network.export_har'
|
|
73
84
|
| 'network.intercept.add'
|
|
74
85
|
| 'network.intercept.remove'
|
|
75
86
|
| 'network.intercept.list'
|
|
@@ -79,6 +90,10 @@ export type BridgeMethod =
|
|
|
79
90
|
| 'navigation.go_back'
|
|
80
91
|
| 'navigation.go_forward'
|
|
81
92
|
| 'dom.query'
|
|
93
|
+
| 'dom.baseline.create'
|
|
94
|
+
| 'dom.baseline.compare'
|
|
95
|
+
| 'dom.baseline.describe'
|
|
96
|
+
| 'dom.baseline.release'
|
|
82
97
|
| 'dom.describe'
|
|
83
98
|
| 'dom.get_text'
|
|
84
99
|
| 'dom.get_attributes'
|
|
@@ -106,6 +121,8 @@ export type BridgeMethod =
|
|
|
106
121
|
| 'screenshot.capture_region'
|
|
107
122
|
| 'screenshot.capture_element'
|
|
108
123
|
| 'screenshot.capture_full_page'
|
|
124
|
+
| 'artifact.read'
|
|
125
|
+
| 'artifact.delete'
|
|
109
126
|
| 'patch.apply_styles'
|
|
110
127
|
| 'patch.apply_dom'
|
|
111
128
|
| 'patch.list'
|
|
@@ -142,9 +159,44 @@ export interface BridgeMeta {
|
|
|
142
159
|
budget_applied?: boolean;
|
|
143
160
|
budget_truncated?: boolean;
|
|
144
161
|
continuation_hint?: string | null;
|
|
162
|
+
automatic_retry?: { attempt: 2; reason: 'retryable_error' };
|
|
163
|
+
stale_recovery?: 'success' | 'failure';
|
|
145
164
|
[key: string]: unknown;
|
|
146
165
|
}
|
|
147
166
|
|
|
167
|
+
export type RecoveryScope = 'routedExtension' | 'daemon';
|
|
168
|
+
|
|
169
|
+
export type RecoveryEventKind =
|
|
170
|
+
| 'automatic_mcp_retry'
|
|
171
|
+
| 'stale_ref_recovery'
|
|
172
|
+
| 'debugger_reattach'
|
|
173
|
+
| 'content_script_reinjection'
|
|
174
|
+
| 'native_host_reconnect'
|
|
175
|
+
| 'request_outcome';
|
|
176
|
+
|
|
177
|
+
export interface RecoveryEventSummary {
|
|
178
|
+
attempts: number;
|
|
179
|
+
successes: number;
|
|
180
|
+
failures: number;
|
|
181
|
+
pending: number;
|
|
182
|
+
saturated: boolean;
|
|
183
|
+
successRate: number | null;
|
|
184
|
+
failureRate: number | null;
|
|
185
|
+
activeLoop: boolean;
|
|
186
|
+
lastEventAt: number | null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export interface RecoveryTelemetrySummary {
|
|
190
|
+
scope: RecoveryScope;
|
|
191
|
+
windowMs: number;
|
|
192
|
+
bucketMs: number;
|
|
193
|
+
loopWindowMs: number;
|
|
194
|
+
loopThreshold: number;
|
|
195
|
+
asOf: number;
|
|
196
|
+
activeLoop: boolean;
|
|
197
|
+
events: Record<RecoveryEventKind, RecoveryEventSummary>;
|
|
198
|
+
}
|
|
199
|
+
|
|
148
200
|
export interface BridgeParams {
|
|
149
201
|
[key: string]: unknown;
|
|
150
202
|
}
|
|
@@ -223,6 +275,147 @@ export interface NormalizedDomQuery extends BridgeParams {
|
|
|
223
275
|
budget: Budget;
|
|
224
276
|
}
|
|
225
277
|
|
|
278
|
+
export interface DomBaselineCreateParams {
|
|
279
|
+
selector?: string;
|
|
280
|
+
maxNodes?: number;
|
|
281
|
+
maxDepth?: number;
|
|
282
|
+
textBudget?: number;
|
|
283
|
+
attributeAllowlist?: string[];
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export interface NormalizedDomBaselineCreateParams extends BridgeParams {
|
|
287
|
+
selector: string;
|
|
288
|
+
maxNodes: number;
|
|
289
|
+
maxDepth: number;
|
|
290
|
+
textBudget: number;
|
|
291
|
+
attributeAllowlist: string[];
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export interface DomBaselineCompareParams {
|
|
295
|
+
baselineId?: string;
|
|
296
|
+
maxChanges?: number;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export interface NormalizedDomBaselineCompareParams extends BridgeParams {
|
|
300
|
+
baselineId: string;
|
|
301
|
+
maxChanges: number;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export interface DomBaselineHandleParams {
|
|
305
|
+
baselineId?: string;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export interface NormalizedDomBaselineHandleParams extends BridgeParams {
|
|
309
|
+
baselineId: string;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export interface DomBaselineOptions {
|
|
313
|
+
maxNodes: number;
|
|
314
|
+
maxDepth: number;
|
|
315
|
+
textBudget: number;
|
|
316
|
+
attributeAllowlist: string[];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export interface DomBaselineScope {
|
|
320
|
+
windowId: number;
|
|
321
|
+
tabId: number;
|
|
322
|
+
frameId: number;
|
|
323
|
+
documentToken: string;
|
|
324
|
+
selector: string;
|
|
325
|
+
representation: 'semantic-dom-v1';
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export interface DomBaselineSnapshotStats {
|
|
329
|
+
nodeCount: number;
|
|
330
|
+
byteLength: number;
|
|
331
|
+
digest: string;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export interface DomBaselineDescriptor {
|
|
335
|
+
baselineId: string;
|
|
336
|
+
createdAt: string;
|
|
337
|
+
expiresAt: string;
|
|
338
|
+
scope: DomBaselineScope;
|
|
339
|
+
options: DomBaselineOptions;
|
|
340
|
+
snapshot: DomBaselineSnapshotStats;
|
|
341
|
+
evicted?: Array<{
|
|
342
|
+
baselineId: string;
|
|
343
|
+
reason: 'per_tab_quota' | 'global_quota';
|
|
344
|
+
}>;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export type DomBaselineCreateResult = DomBaselineDescriptor;
|
|
348
|
+
export type DomBaselineDescribeResult = DomBaselineDescriptor;
|
|
349
|
+
|
|
350
|
+
export interface DomBaselineSemanticNodeEvidence {
|
|
351
|
+
tag: string;
|
|
352
|
+
role: string | null;
|
|
353
|
+
name: string | null;
|
|
354
|
+
text: string;
|
|
355
|
+
attributes: Record<string, string>;
|
|
356
|
+
depth: number;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export type DomBaselineNodeEvidence = DomBaselineSemanticNodeEvidence;
|
|
360
|
+
|
|
361
|
+
export interface DomBaselineChangedNode {
|
|
362
|
+
fields: string[];
|
|
363
|
+
before: DomBaselineSemanticNodeEvidence;
|
|
364
|
+
after: DomBaselineSemanticNodeEvidence;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export interface DomBaselineNodeLocation {
|
|
368
|
+
ancestry: string[];
|
|
369
|
+
order: number;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export interface DomBaselineMovedNode {
|
|
373
|
+
node: DomBaselineSemanticNodeEvidence;
|
|
374
|
+
from: DomBaselineNodeLocation;
|
|
375
|
+
to: DomBaselineNodeLocation;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export interface DomBaselineChangeCounts {
|
|
379
|
+
added: number;
|
|
380
|
+
removed: number;
|
|
381
|
+
changed: number;
|
|
382
|
+
moved: number;
|
|
383
|
+
unchanged: number;
|
|
384
|
+
total: number;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export interface DomBaselineReturnedCounts {
|
|
388
|
+
added: number;
|
|
389
|
+
removed: number;
|
|
390
|
+
changed: number;
|
|
391
|
+
moved: number;
|
|
392
|
+
total: number;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export interface DomBaselineCompareResult {
|
|
396
|
+
baselineId: string;
|
|
397
|
+
equal: boolean;
|
|
398
|
+
comparedAt: string;
|
|
399
|
+
counts: DomBaselineChangeCounts;
|
|
400
|
+
returnedCounts: DomBaselineReturnedCounts;
|
|
401
|
+
added: DomBaselineSemanticNodeEvidence[];
|
|
402
|
+
removed: DomBaselineSemanticNodeEvidence[];
|
|
403
|
+
changed: DomBaselineChangedNode[];
|
|
404
|
+
moved: DomBaselineMovedNode[];
|
|
405
|
+
truncated: boolean;
|
|
406
|
+
omittedChanges: number;
|
|
407
|
+
ambiguity: {
|
|
408
|
+
count: number;
|
|
409
|
+
examples: DomBaselineSemanticNodeEvidence[];
|
|
410
|
+
};
|
|
411
|
+
guidance: string;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export interface DomBaselineReleaseResult {
|
|
415
|
+
baselineId: string;
|
|
416
|
+
released: boolean;
|
|
417
|
+
}
|
|
418
|
+
|
|
226
419
|
export interface DomFindResult {
|
|
227
420
|
found: boolean;
|
|
228
421
|
nodes: Record<string, unknown>[];
|
|
@@ -312,6 +505,10 @@ export interface CdpNodeIdParams {
|
|
|
312
505
|
nodeId?: number;
|
|
313
506
|
}
|
|
314
507
|
|
|
508
|
+
export interface CdpDomSnapshotParams {
|
|
509
|
+
computedStyles?: string[];
|
|
510
|
+
}
|
|
511
|
+
|
|
315
512
|
export interface NormalizedCdpDispatchKeyEventParams extends BridgeParams {
|
|
316
513
|
key: string;
|
|
317
514
|
code: string;
|
|
@@ -322,6 +519,10 @@ export interface NormalizedCdpNodeIdParams extends BridgeParams {
|
|
|
322
519
|
nodeId: number;
|
|
323
520
|
}
|
|
324
521
|
|
|
522
|
+
export interface NormalizedCdpDomSnapshotParams extends BridgeParams {
|
|
523
|
+
computedStyles: string[];
|
|
524
|
+
}
|
|
525
|
+
|
|
325
526
|
export interface CheckedActionParams {
|
|
326
527
|
target?: InputTarget;
|
|
327
528
|
checked?: boolean;
|
|
@@ -594,10 +795,31 @@ export interface NormalizedStorageParams extends BridgeParams {
|
|
|
594
795
|
keys: string[] | null;
|
|
595
796
|
}
|
|
596
797
|
|
|
798
|
+
export type SensitiveStorageSource = 'local_storage' | 'session_storage';
|
|
799
|
+
|
|
800
|
+
export interface SensitiveReadParams {
|
|
801
|
+
source: SensitiveStorageSource;
|
|
802
|
+
key: string;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
export interface NormalizedSensitiveReadParams extends BridgeParams {
|
|
806
|
+
source: SensitiveStorageSource;
|
|
807
|
+
key: string;
|
|
808
|
+
maxBytes: number;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
export interface SensitiveReadResult {
|
|
812
|
+
source: SensitiveStorageSource;
|
|
813
|
+
value: string;
|
|
814
|
+
exact: true;
|
|
815
|
+
}
|
|
816
|
+
|
|
597
817
|
export type ExtractContentFormat = 'text' | 'markdown';
|
|
598
818
|
export type ExtractContentConsistency = 'best_effort' | 'settled';
|
|
599
819
|
export type ExtractContentSource = 'readability' | 'semantic-root' | 'body';
|
|
600
820
|
export type ScreenshotFormat = 'png' | 'jpeg' | 'webp';
|
|
821
|
+
export type ScreenshotDelivery = 'auto' | 'inline' | 'artifact';
|
|
822
|
+
export type ArtifactKind = 'screenshot' | 'har';
|
|
601
823
|
|
|
602
824
|
export interface ExtractContentParams {
|
|
603
825
|
format?: ExtractContentFormat;
|
|
@@ -620,22 +842,62 @@ export interface NormalizedExtractContentParams extends BridgeParams {
|
|
|
620
842
|
export interface ScreenshotParams extends BridgeParams {
|
|
621
843
|
format?: ScreenshotFormat;
|
|
622
844
|
quality?: number;
|
|
845
|
+
delivery?: ScreenshotDelivery;
|
|
846
|
+
scale?: number;
|
|
623
847
|
}
|
|
624
848
|
|
|
625
849
|
export interface NormalizedScreenshotParams extends BridgeParams {
|
|
626
850
|
format: ScreenshotFormat;
|
|
627
851
|
quality: number | null;
|
|
852
|
+
delivery: ScreenshotDelivery;
|
|
853
|
+
scale: number;
|
|
628
854
|
}
|
|
629
855
|
|
|
630
|
-
export interface
|
|
631
|
-
|
|
856
|
+
export interface ArtifactDescriptor<K extends ArtifactKind = ArtifactKind> {
|
|
857
|
+
artifactId: string;
|
|
858
|
+
kind: K;
|
|
859
|
+
mimeType: string;
|
|
860
|
+
byteLength: number;
|
|
861
|
+
sha256: string;
|
|
862
|
+
chunkSize: number;
|
|
863
|
+
chunkCount: number;
|
|
864
|
+
createdAt: string;
|
|
865
|
+
expiresAt: string;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
export interface ScreenshotMetadata {
|
|
632
869
|
mimeType: `image/${ScreenshotFormat}`;
|
|
633
870
|
format: ScreenshotFormat;
|
|
871
|
+
byteLength: number;
|
|
872
|
+
dimensions: { width: number; height: number };
|
|
634
873
|
rect: { x: number; y: number; width: number; height: number; scale: number };
|
|
635
874
|
complete: boolean;
|
|
636
875
|
clipped: boolean;
|
|
637
876
|
}
|
|
638
877
|
|
|
878
|
+
export type ScreenshotResult =
|
|
879
|
+
| (ScreenshotMetadata & { delivery: 'inline'; image: string })
|
|
880
|
+
| (ScreenshotMetadata & {
|
|
881
|
+
delivery: 'artifact';
|
|
882
|
+
artifact: ArtifactDescriptor<'screenshot'>;
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
export interface ArtifactReadParams extends BridgeParams {
|
|
886
|
+
artifactId?: string;
|
|
887
|
+
offset?: number;
|
|
888
|
+
maxBytes?: number;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
export interface NormalizedArtifactReadParams extends BridgeParams {
|
|
892
|
+
artifactId: string;
|
|
893
|
+
offset: number;
|
|
894
|
+
maxBytes: number;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
export interface ArtifactDeleteParams extends BridgeParams {
|
|
898
|
+
artifactId?: string;
|
|
899
|
+
}
|
|
900
|
+
|
|
639
901
|
export interface ExtractContentResult {
|
|
640
902
|
format: ExtractContentFormat;
|
|
641
903
|
content: string;
|
|
@@ -799,6 +1061,229 @@ export interface NetworkResult {
|
|
|
799
1061
|
truncation: { reason: 'limit' | null; limit: number; omitted: number };
|
|
800
1062
|
}
|
|
801
1063
|
|
|
1064
|
+
export interface CdpPerformanceMetric {
|
|
1065
|
+
name: string;
|
|
1066
|
+
value: number;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
export interface PerformanceMeasurement {
|
|
1070
|
+
source: 'cdp.Performance.getMetrics';
|
|
1071
|
+
kind: 'raw_cdp_counters';
|
|
1072
|
+
sampledAt: string;
|
|
1073
|
+
timeDomain: 'timeTicks';
|
|
1074
|
+
observation: 'browser_maintained_point_sample';
|
|
1075
|
+
webVitals: 'not_measured';
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
export interface PerformanceMetricsResult {
|
|
1079
|
+
metrics: Record<string, number>;
|
|
1080
|
+
measurement: PerformanceMeasurement;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
export type HarDelivery = 'auto' | 'inline' | 'artifact';
|
|
1084
|
+
export type HarCaptureState = NetworkResult['captureState'];
|
|
1085
|
+
|
|
1086
|
+
export interface HarExportParams {
|
|
1087
|
+
limit?: number;
|
|
1088
|
+
urlPattern?: string;
|
|
1089
|
+
delivery?: HarDelivery;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
export interface NormalizedHarExportParams extends BridgeParams {
|
|
1093
|
+
limit: number;
|
|
1094
|
+
urlPattern: string | null;
|
|
1095
|
+
delivery: HarDelivery;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
export interface HarEvidenceEntry extends Record<string, unknown> {
|
|
1099
|
+
url: string;
|
|
1100
|
+
method: string;
|
|
1101
|
+
resourceType: string;
|
|
1102
|
+
status: number;
|
|
1103
|
+
mimeType: string;
|
|
1104
|
+
protocol: string;
|
|
1105
|
+
fromCache: boolean;
|
|
1106
|
+
fromDiskCache: boolean;
|
|
1107
|
+
fromServiceWorker: boolean;
|
|
1108
|
+
fromPrefetchCache: boolean;
|
|
1109
|
+
failureReason: string;
|
|
1110
|
+
redirectURL: string;
|
|
1111
|
+
duration: number;
|
|
1112
|
+
startedAt: number;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
export interface HarNameValue extends Record<string, unknown> {
|
|
1116
|
+
name: string;
|
|
1117
|
+
value: string;
|
|
1118
|
+
comment?: string;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
export interface HarCookie extends HarNameValue {
|
|
1122
|
+
path?: string;
|
|
1123
|
+
domain?: string;
|
|
1124
|
+
expires?: string;
|
|
1125
|
+
httpOnly?: boolean;
|
|
1126
|
+
secure?: boolean;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
export interface HarPostDataParam extends HarNameValue {
|
|
1130
|
+
fileName?: string;
|
|
1131
|
+
contentType?: string;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
export interface HarPostData extends Record<string, unknown> {
|
|
1135
|
+
mimeType: string;
|
|
1136
|
+
params?: HarPostDataParam[];
|
|
1137
|
+
text?: string;
|
|
1138
|
+
comment?: string;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
export interface HarRequest extends Record<string, unknown> {
|
|
1142
|
+
method: string;
|
|
1143
|
+
url: string;
|
|
1144
|
+
httpVersion: string;
|
|
1145
|
+
cookies: HarCookie[];
|
|
1146
|
+
headers: HarNameValue[];
|
|
1147
|
+
queryString: HarNameValue[];
|
|
1148
|
+
postData?: HarPostData;
|
|
1149
|
+
headersSize: number;
|
|
1150
|
+
bodySize: number;
|
|
1151
|
+
comment?: string;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
export interface HarContent extends Record<string, unknown> {
|
|
1155
|
+
size: number;
|
|
1156
|
+
compression?: number;
|
|
1157
|
+
mimeType: string;
|
|
1158
|
+
text?: string;
|
|
1159
|
+
encoding?: string;
|
|
1160
|
+
comment?: string;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
export interface HarResponse extends Record<string, unknown> {
|
|
1164
|
+
status: number;
|
|
1165
|
+
statusText: string;
|
|
1166
|
+
httpVersion: string;
|
|
1167
|
+
cookies: HarCookie[];
|
|
1168
|
+
headers: HarNameValue[];
|
|
1169
|
+
content: HarContent;
|
|
1170
|
+
redirectURL: string;
|
|
1171
|
+
headersSize: number;
|
|
1172
|
+
bodySize: number;
|
|
1173
|
+
comment?: string;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
export interface HarCacheInfo extends Record<string, unknown> {
|
|
1177
|
+
expires?: string;
|
|
1178
|
+
lastAccess: string;
|
|
1179
|
+
eTag: string;
|
|
1180
|
+
hitCount: number;
|
|
1181
|
+
comment?: string;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
export interface HarCache extends Record<string, unknown> {
|
|
1185
|
+
beforeRequest?: HarCacheInfo;
|
|
1186
|
+
afterRequest?: HarCacheInfo;
|
|
1187
|
+
comment?: string;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
export interface HarTimings extends Record<string, unknown> {
|
|
1191
|
+
blocked?: number;
|
|
1192
|
+
dns?: number;
|
|
1193
|
+
connect?: number;
|
|
1194
|
+
send: number;
|
|
1195
|
+
wait: number;
|
|
1196
|
+
receive: number;
|
|
1197
|
+
ssl?: number;
|
|
1198
|
+
comment?: string;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
export interface HarPageTimings extends Record<string, unknown> {
|
|
1202
|
+
onContentLoad?: number;
|
|
1203
|
+
onLoad?: number;
|
|
1204
|
+
comment?: string;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
export interface HarPage extends Record<string, unknown> {
|
|
1208
|
+
startedDateTime: string;
|
|
1209
|
+
id: string;
|
|
1210
|
+
title: string;
|
|
1211
|
+
pageTimings: HarPageTimings;
|
|
1212
|
+
comment?: string;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
export interface HarCreator extends Record<string, unknown> {
|
|
1216
|
+
name: string;
|
|
1217
|
+
version: string;
|
|
1218
|
+
comment?: string;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
export interface HarEntry extends Record<string, unknown> {
|
|
1222
|
+
pageref?: string;
|
|
1223
|
+
startedDateTime: string;
|
|
1224
|
+
time: number;
|
|
1225
|
+
request: HarRequest;
|
|
1226
|
+
response: HarResponse;
|
|
1227
|
+
cache: HarCache;
|
|
1228
|
+
timings: HarTimings;
|
|
1229
|
+
serverIPAddress?: string;
|
|
1230
|
+
connection?: string;
|
|
1231
|
+
comment?: string;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
export interface HarLog extends Record<string, unknown> {
|
|
1235
|
+
version: '1.2';
|
|
1236
|
+
creator: HarCreator;
|
|
1237
|
+
browser?: HarCreator;
|
|
1238
|
+
pages?: HarPage[];
|
|
1239
|
+
entries: HarEntry[];
|
|
1240
|
+
comment?: string;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
export interface HarDocument extends Record<string, unknown> {
|
|
1244
|
+
log: HarLog;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
export interface HarExportTruncation {
|
|
1248
|
+
reason: 'limit' | 'inline_bytes' | null;
|
|
1249
|
+
limit: number;
|
|
1250
|
+
omitted: number;
|
|
1251
|
+
omittedByLimit: number;
|
|
1252
|
+
omittedBySize: number;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
export interface HarExportMetadata {
|
|
1256
|
+
format: 'har';
|
|
1257
|
+
harVersion: '1.2';
|
|
1258
|
+
mimeType: 'application/json';
|
|
1259
|
+
byteLength: number;
|
|
1260
|
+
entryCount: number;
|
|
1261
|
+
totalEntries: number;
|
|
1262
|
+
dropped: number;
|
|
1263
|
+
abandoned: number;
|
|
1264
|
+
inflight: number;
|
|
1265
|
+
startedAt: number | null;
|
|
1266
|
+
captureState: HarCaptureState;
|
|
1267
|
+
truncated: boolean;
|
|
1268
|
+
truncation: HarExportTruncation;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
export type HarExportResult =
|
|
1272
|
+
| (HarExportMetadata & { delivery: 'inline'; har: HarDocument })
|
|
1273
|
+
| (HarExportMetadata & {
|
|
1274
|
+
delivery: 'artifact';
|
|
1275
|
+
artifact: ArtifactDescriptor<'har'>;
|
|
1276
|
+
});
|
|
1277
|
+
|
|
1278
|
+
export interface HarExportEvidence {
|
|
1279
|
+
delivery: HarExportResult['delivery'];
|
|
1280
|
+
entryCount: number;
|
|
1281
|
+
totalEntries: number;
|
|
1282
|
+
dropped: number;
|
|
1283
|
+
abandoned: number;
|
|
1284
|
+
inflight: number;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
802
1287
|
export type NetworkInterceptAction = 'fulfill' | 'continue' | 'block';
|
|
803
1288
|
|
|
804
1289
|
export interface NetworkInterceptAddParams {
|
|
@@ -59,11 +59,13 @@ bbx a11y-tree [maxNodes] [maxDepth] # accessibility tree
|
|
|
59
59
|
bbx eval [--await] <expression> # JS eval (--await for promises, - for stdin)
|
|
60
60
|
bbx console [level] # console output
|
|
61
61
|
bbx network [limit] # recent fetch/XHR requests
|
|
62
|
+
bbx har [options] [outPath] # export armed CDP capture as sanitized HAR 1.2
|
|
62
63
|
bbx intercept add <pattern> [--respond <body>] [--status <code>] [--block] # intercept matching requests
|
|
63
64
|
bbx intercept list|remove <id>|clear # manage interception rules
|
|
64
65
|
bbx page-text [budget] # full page text
|
|
65
|
-
bbx storage [local|session] [keys] #
|
|
66
|
-
bbx
|
|
66
|
+
bbx storage [local|session] [keys] # storage key/presence metadata
|
|
67
|
+
bbx call sensitive.read '{"source":"local_storage","key":"name"}' # deliberate exact value
|
|
68
|
+
bbx perf # raw Chrome/CDP counter point sample
|
|
67
69
|
bbx navigate <url> # navigate to URL
|
|
68
70
|
bbx reload # reload current page
|
|
69
71
|
bbx back # navigate back
|
|
@@ -145,7 +147,7 @@ After access is enabled:
|
|
|
145
147
|
| `DIALOG_ACTION_CONFLICT` | No | Inspect current dialog state; never auto-repeat accept/dismiss |
|
|
146
148
|
| `TAB_MISMATCH` | No | Tab closed or not found - use `tabs.list` to find an available tab |
|
|
147
149
|
| `TIMEOUT` | Once | Retry once; if still failing, simplify (smaller `maxNodes`, narrower selector) |
|
|
148
|
-
| `
|
|
150
|
+
| `CONTENT_SCRIPT_UNAVAILABLE` | No | Switch to a normal http(s) page in the enabled window |
|
|
149
151
|
| `EXTENSION_DISCONNECTED` | After 3s | Check Chrome is running; `bbx status` to verify, then retry |
|
|
150
152
|
| `NATIVE_HOST_UNAVAILABLE` | No | Run `bbx doctor` to diagnose the installation |
|
|
151
153
|
| `INTERNAL_ERROR` | Once | Retry once; if persistent, check `page.get_console` for details |
|
|
@@ -155,6 +157,13 @@ After access is enabled:
|
|
|
155
157
|
|
|
156
158
|
Error responses now include a machine-readable `error.recovery` field with `retry`, `retryAfterMs`, `alternativeMethod`, and `hint`.
|
|
157
159
|
|
|
160
|
+
`health.ping`, `daemon.metrics`, and `bbx doctor` also expose process-local
|
|
161
|
+
five-minute recovery summaries for six fixed, content-free categories. Three
|
|
162
|
+
failures in the same hidden group within 60 seconds marks an active loop. Stop
|
|
163
|
+
repeating the action and follow Doctor's fixed category guidance. Extension
|
|
164
|
+
summaries reset on service-worker restart and daemon summaries on daemon restart;
|
|
165
|
+
they contain no page data, URLs, selectors, payloads, errors, or group names.
|
|
166
|
+
|
|
158
167
|
## Core Rules
|
|
159
168
|
|
|
160
169
|
1. **Work in existing tabs** - Never create new tabs unless the user explicitly asks for it, or the task absolutely requires a fresh page (e.g., testing a clean state, comparing across URLs). Prefer `tabs.list` to find an appropriate existing tab.
|
|
@@ -168,7 +177,8 @@ Error responses now include a machine-readable `error.recovery` field with `retr
|
|
|
168
177
|
9. **Batch reads** - combine independent reads with `bbx batch` in CLI mode or `browser_batch` in MCP mode; do not pass `batch` as a `browser_call` method.
|
|
169
178
|
10. **Avoid debugger first** - prefer DOM/content-script methods (`dom.*`, `styles.*`, `layout.get_box_model`, `page.get_console`, `page.get_text`, `page.get_storage`, `page.get_network`) before any debugger-backed method. Escalate to CDP only when those cannot answer the question.
|
|
170
179
|
11. **Evaluate only when needed** - `page.evaluate` is powerful but debugger-backed; use it only when DOM, storage, console, network, or text reads cannot expose the needed state.
|
|
171
|
-
12. **
|
|
180
|
+
12. **Treat exact storage as sensitive** - use `page.get_storage` for metadata first. Call `sensitive.read` for one exact key only when necessary; never batch or automatically retry it, and never repeat a failed attempt without new evidence.
|
|
181
|
+
12. **Debugger-backed methods are last resort** - treat `page.evaluate`, `page.handle_dialog`, `dom.get_accessibility_tree`, `page.get_network` with `source: 'cdp'`, input with `executionMode: 'cdp'`, `viewport.resize`, `performance.get_metrics`, `screenshot.capture_*`, and all `cdp.*` methods as escalation steps because they attach `chrome.debugger`. `performance.get_metrics` is a raw browser-maintained CDP counter point sample, not Web Vitals.
|
|
172
182
|
13. **Wait after change** - after editing source, wait for expected new text, a selector matching the changed attribute, or a detach/attach remount; waiting for `attached` on a selector that already exists does not prove HMR ran. Use `page.wait_for_load_state` for navigation, not HMR.
|
|
173
183
|
14. **Prime event buffers** - before reproducing a console or fetch/XHR issue, call `page.get_console` and default `page.get_network` once with `clear: true`; then reproduce and read without clearing. CDP all-resource capture instead requires explicit `start`, reproduce, `read`, and `stop` calls.
|
|
174
184
|
15. **Semantic finding** - use `dom.find_by_text` / `dom.find_by_role` when you know the label but not the selector.
|
|
@@ -180,6 +190,8 @@ Error responses now include a machine-readable `error.recovery` field with `retr
|
|
|
180
190
|
21. **Do not guess input targets** - for targeted click, focus, type, fill, press-key, checked-state, option-selection, hover, and drag calls, honor actionability errors and returned `resolution` metadata. `cdp_press_key` and `scroll_into_view` use separate contracts. `executionMode` is only `dom` or `cdp`; `input.fill.mode: auto` is a separate DOM setter/keystroke strategy.
|
|
181
191
|
22. **Stale recovery stays opt-in** - prefer re-querying. Use `recoverStale: true` once only when the same document/URL and a strong unique semantic descriptor should still identify the target; inspect `recovered`, old/new refs, and matched fields. A scan with more than 100 same-tag candidates fails as `ELEMENT_AMBIGUOUS`/`scan_incomplete` because uniqueness is not provable.
|
|
182
192
|
23. **Dialogs are explicit** - inspect first, then accept or dismiss only when intended. `expectedDialogId` is a pre-dispatch stale-decision check, not an atomic CDP binding; never auto-repeat `DIALOG_ACTION_CONFLICT`.
|
|
193
|
+
24. **DOM diffs use explicit baselines** - call `dom.baseline.create` before the action, `dom.baseline.compare` afterward, then `dom.baseline.release`. Use a narrow selector and bounded evidence. Never substitute unrelated DOM reads for the retained baseline, and recreate it after `DOM_BASELINE_INVALIDATED`.
|
|
194
|
+
25. **HAR export reads an armed capture** - use CDP capture `start`, reproduce, `network.export_har`/`bbx har`, then `stop`. Export never starts, stops, or clears capture. Inspect truncation plus `dropped`, `abandoned`, and `inflight` before claiming completeness.
|
|
183
195
|
|
|
184
196
|
## Token Budget Quick Rules
|
|
185
197
|
|
|
@@ -251,12 +263,12 @@ bbx page-text 2000 # extract page content
|
|
|
251
263
|
| Find | `dom.find_by_text`, `dom.find_by_role`, `dom.wait_for`, `dom.get_accessibility_tree` |
|
|
252
264
|
| Page State | `page.get_console`, `page.get_storage`, `page.get_text`, `page.wait_for_load_state`, `page.evaluate` (debugger-backed) |
|
|
253
265
|
| Dialogs | `page.handle_dialog` (debugger-backed; explicit inspect/accept/dismiss only) |
|
|
254
|
-
| Network | `page.get_network` (fetch/XHR default; optional CDP lifecycle), `network.intercept.add/remove/list/clear` (debugger-backed)
|
|
266
|
+
| Network | `page.get_network` (fetch/XHR default; optional CDP lifecycle), `network.export_har`, `network.intercept.add/remove/list/clear` (debugger-backed) |
|
|
255
267
|
| Interact | `input.click`, `input.type`, `input.fill`, `input.focus`, `input.press_key`, `cdp.dispatch_key_event`, `input.hover`, `input.drag`, `input.scroll_into_view` |
|
|
256
268
|
| Tabs | `tabs.list` (preferred), `tabs.create` (avoid unless necessary), `tabs.close`, `tabs.activate` |
|
|
257
269
|
| Patch | `patch.apply_styles`, `patch.apply_dom`, `patch.rollback` |
|
|
258
270
|
| Navigate | `navigation.navigate`, `viewport.scroll`, `viewport.resize` |
|
|
259
|
-
| Performance | `performance.get_metrics` (debugger-backed)
|
|
271
|
+
| Performance | `performance.get_metrics` (raw Chrome/CDP counter point sample; debugger-backed) |
|
|
260
272
|
| Escalate | `dom.get_accessibility_tree`, `screenshot.capture_element`, `screenshot.capture_region` (tight crops only), `screenshot.capture_full_page`, `cdp.*` |
|
|
261
273
|
|
|
262
274
|
## Dev-Server Workflow (HMR-aware)
|
|
@@ -336,8 +348,9 @@ Every CLI shortcut command produces consistent `{ok, summary, evidence}` JSON. U
|
|
|
336
348
|
- `input.drag` uses `source`, `destination`, and optional destination offsets `offsetX` / `offsetY`.
|
|
337
349
|
- `executionMode` accepts `dom` or `cdp` and defaults to `dom`; CDP supports only click, hover, drag, type, and fill. `input.fill.mode` (`auto`, `setter`, `keystrokes`) is a separate DOM strategy.
|
|
338
350
|
- `page.get_network` defaults to low-cost fetch/XHR instrumentation. All-resource CDP capture must be armed before the activity with `source: "cdp", capture: "start"`, read later, and explicitly stopped.
|
|
351
|
+
- `network.export_har` requires that explicit capture to still be armed. Params are `limit` (1-200), sanitized-URL substring `urlPattern`, and `delivery` (`auto`, `inline`, `artifact`). Inline bounds remove whole oldest entries; export never changes capture state. `bbx har` uses the same client to download, length/SHA-256 verify, delete, validate, and atomically write artifacts locally.
|
|
339
352
|
- `page.handle_dialog` mutations are not atomically bound to `expectedDialogId`; treat `commandDispatched` as dispatch evidence and verify follow-up state.
|
|
340
|
-
- Raw
|
|
353
|
+
- Raw screenshot calls default to inline base64. Use `delivery: "auto"` for size-aware artifact fallback, or explicit `inline` when MCP image content is required; prefer `bbx screenshot <ref> [outPath]` when one element is enough because the CLI downloads and verifies artifacts locally.
|
|
341
354
|
|
|
342
355
|
## Response Shapes
|
|
343
356
|
|
|
@@ -360,13 +373,14 @@ Shortcut commands intentionally expose only the common case. Use `bbx call <meth
|
|
|
360
373
|
| Computed styles | `result.properties + elementRef` | `Computed N style(s) for ref.` |
|
|
361
374
|
| Box model | `result.content + border` | `Box model: W×H at (x, y).` |
|
|
362
375
|
| Network | `result.source + entries` | `Network: N requests.` |
|
|
376
|
+
| HAR export | `result.format === "har"` | `HAR export delivered mode: N/M entries.` |
|
|
363
377
|
| Console | `entries` (no type field) | `Console: N entries.` |
|
|
364
378
|
| Logs | `entries[0].at + method` | `Log: N entries.` |
|
|
365
379
|
| Patch apply | `result.patchId` | `Patch id applied.` |
|
|
366
380
|
| Patch rollback | `result.rolled_back` | `Patch rolled back.` |
|
|
367
381
|
| Patch list | `result.patches` | `N active patch(es).` |
|
|
368
382
|
| HTML | `result.html` | `HTML fragment: N chars.` |
|
|
369
|
-
| Performance | `result.metrics` | `
|
|
383
|
+
| Performance | `result.metrics` | `Raw CDP performance counters: N collected; Web Vitals not measured.` |
|
|
370
384
|
| Storage | `result.type + count + entries` | `Storage (type): N entries.` |
|
|
371
385
|
| Click/Focus/Type | `result.clicked/focused/typed` | `Clicked/Focused/Typed ref.` |
|
|
372
386
|
| Key press | `result.pressed` | `Key pressed (key).` |
|