humanish 0.136.0 → 0.137.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/CHANGELOG.md +22 -0
- package/dist/actors/computer-use/actor.d.ts +2 -0
- package/dist/actors/computer-use/actor.js +1 -0
- package/dist/actors/computer-use/loop/observation.js +2 -0
- package/dist/actors/computer-use/loop/session.d.ts +3 -2
- package/dist/actors/computer-use/loop/session.js +8 -12
- package/dist/actors/computer-use/loop/types.d.ts +14 -1
- package/dist/evidence/browser-network.d.ts +108 -0
- package/dist/evidence/browser-network.js +516 -0
- package/dist/evidence/trace-page.d.ts +31 -1
- package/dist/evidence/trace-page.js +68 -2
- package/dist/observer-app.html +4 -4
- package/dist/routes/computer-use/bundle.js +1 -0
- package/dist/routes/computer-use/e2b-desktop/desktop.js +6 -0
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +12 -1
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +7 -2
- package/dist/routes/computer-use/e2b-desktop/network.d.ts +52 -0
- package/dist/routes/computer-use/e2b-desktop/network.js +153 -0
- package/dist/routes/computer-use/e2b-desktop/start.js +18 -1
- package/dist/routes/computer-use/e2b-desktop/state.d.ts +3 -0
- package/dist/routes/computer-use/e2b-desktop/state.js +2 -0
- package/dist/routes/computer-use/e2b-desktop/teardown.js +6 -3
- package/dist/routes/computer-use/fanout-records.js +10 -0
- package/dist/routes/computer-use/participant-desktop.d.ts +7 -2
- package/dist/routes/computer-use/participant-model.js +2 -1
- package/dist/routes/computer-use/plan.js +2 -1
- package/dist/routes/computer-use/single-bundle.d.ts +3 -0
- package/dist/routes/computer-use/single-bundle.js +4 -0
- package/dist/routes/computer-use/types.d.ts +7 -0
- package/dist/routes/scripted/plan.js +2 -2
- package/dist/routes/shared-world/plan.js +3 -2
- package/dist/routes/terminal/plan.js +2 -2
- package/dist/run/live-items.d.ts +20 -2
- package/dist/run/live-items.js +23 -14
- package/dist/run/streams.d.ts +7 -0
- package/dist/study/config.js +4 -1
- package/dist/study/keys.d.ts +3 -0
- package/dist/study/keys.js +2 -0
- package/dist/study/parse/comms.js +1 -20
- package/dist/study/parse/execution.js +30 -1
- package/dist/study/parse/values.d.ts +5 -0
- package/dist/study/parse/values.js +22 -0
- package/dist/study/plan-base.js +6 -1
- package/dist/study/plan-types.d.ts +1 -1
- package/dist/study/study-fields.d.ts +7 -1
- package/dist/study/study-fields.js +10 -0
- package/dist/study/types.d.ts +11 -0
- package/dist/study/validation.d.ts +8 -0
- package/dist/study/validation.js +31 -2
- package/dist/substrates/detached.d.ts +5 -0
- package/dist/substrates/detached.js +9 -0
- package/dist/substrates/e2b/cdp-network-capture.d.ts +23 -0
- package/dist/substrates/e2b/cdp-network-capture.js +194 -0
- package/dist/substrates/e2b/cdp-probe.d.ts +20 -5
- package/dist/substrates/e2b/cdp-probe.js +100 -36
- package/dist/substrates/e2b/desktop-cdp.d.ts +32 -2
- package/dist/substrates/e2b/desktop-cdp.js +87 -5
- package/dist/verify/network.d.ts +10 -0
- package/dist/verify/network.js +162 -0
- package/dist/verify/pages.js +1 -16
- package/dist/verify/verify.js +8 -2
- package/docs/contracts/run-bundle.md +86 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,28 @@ The Unreleased section holds the full notes for the next version until it is tag
|
|
|
8
8
|
|
|
9
9
|
## Unreleased
|
|
10
10
|
|
|
11
|
+
## 0.137.0: Each browser participant can record its requests (2026-10-16)
|
|
12
|
+
|
|
13
|
+
humanish 0.137.0 can record the requests each hosted browser participant makes. With
|
|
14
|
+
`execution.network: true`, a computer-use participant in Chrome or Chromium writes
|
|
15
|
+
`network/<participant id>.ndjson`: one line per request hop with its turn, method, origin and
|
|
16
|
+
path, status, duration, and whether it failed or was still open. A 500 on add-to-cart or a list
|
|
17
|
+
call that never returns now sits next to the turn that started it. The file holds no headers,
|
|
18
|
+
cookies, bodies or query strings, verify checks every record against the contract, and capture is
|
|
19
|
+
off unless a study turns it on.
|
|
20
|
+
|
|
21
|
+
[Release notes](https://github.com/danielgwilson/humanish/releases/tag/v0.137.0)
|
|
22
|
+
|
|
23
|
+
## 0.136.1: The emulation log no longer holds page addresses (2026-10-16)
|
|
24
|
+
|
|
25
|
+
humanish 0.136.1 keeps page addresses out of a mobile-emulated participant's emulation log. The
|
|
26
|
+
log held the full address of each tab the emulation holder reloaded or attached to, query string
|
|
27
|
+
and fragment included, and run.json keeps up to 50 of its lines. A one-time code or token in a URL
|
|
28
|
+
the participant opened could reach a `share_ready` bundle, since verify's text scan does not read a
|
|
29
|
+
short query value as a secret. The log now names the tab's target id and the commands sent.
|
|
30
|
+
|
|
31
|
+
[Release notes](https://github.com/danielgwilson/humanish/releases/tag/v0.136.1)
|
|
32
|
+
|
|
11
33
|
## 0.136.0: verify takes less than half the time on large runs (2026-10-14)
|
|
12
34
|
|
|
13
35
|
humanish 0.136.0 makes `humanish verify` take less than half the time on large runs. It checks a
|
|
@@ -80,6 +80,8 @@ export interface CuaActorSessionOptions {
|
|
|
80
80
|
onScreenshot?: (frame: Buffer) => void;
|
|
81
81
|
/** Whether the trace carries the observed page, threaded to the loop; see LoopRunOptions.recordPages. */
|
|
82
82
|
recordPages?: boolean;
|
|
83
|
+
/** Runtime-only checkpoint callback threaded to the loop; see LoopRunOptions.onCheckpoint. */
|
|
84
|
+
onCheckpoint?: (turnNumber: number) => void;
|
|
83
85
|
/** Per-turn trace snapshot callback threaded to the loop; see CuaLoopOptions.onTrace. */
|
|
84
86
|
onTrace?: (items: readonly ActorTraceItem[], usage: ActorTokenUsage, metadata?: CuaLiveMetadata) => void;
|
|
85
87
|
}
|
|
@@ -58,6 +58,7 @@ export async function runCuaActorSession(options) {
|
|
|
58
58
|
...(options.onScreenshot === undefined ? {} : { onScreenshot: options.onScreenshot }),
|
|
59
59
|
...(options.onTrace === undefined ? {} : { onTrace: options.onTrace }),
|
|
60
60
|
...(options.recordPages === undefined ? {} : { recordPages: options.recordPages }),
|
|
61
|
+
...(options.onCheckpoint === undefined ? {} : { onCheckpoint: options.onCheckpoint }),
|
|
61
62
|
};
|
|
62
63
|
const result = await runComputerUseLoopWithTaps(loopOptions);
|
|
63
64
|
if (result.trace.executionProfile?.billing === "account-unknown") {
|
|
@@ -51,6 +51,7 @@ export class DesktopObserver {
|
|
|
51
51
|
if (frameless !== undefined)
|
|
52
52
|
return { stop: frameless };
|
|
53
53
|
await this.recordScreenshot(observation, opening ? "turn-00-start" : `turn-${pad(turnNumber)}`);
|
|
54
|
+
session.settings.onCheckpoint?.(turnNumber);
|
|
54
55
|
session.flush();
|
|
55
56
|
this.observeTasks(observation, turnNumber);
|
|
56
57
|
const dwell = await this.dwellIfDue(observation, turnNumber);
|
|
@@ -58,6 +59,7 @@ export class DesktopObserver {
|
|
|
58
59
|
if (dwell !== undefined) {
|
|
59
60
|
observation = this.handToHooks(this.withHeardSpeech(await this.observeBounded("after dwell")));
|
|
60
61
|
await this.recordScreenshot(observation, `turn-${pad(turnNumber)}-after-dwell`);
|
|
62
|
+
session.settings.onCheckpoint?.(turnNumber);
|
|
61
63
|
this.observeTasks(observation, turnNumber);
|
|
62
64
|
if (dwell.next === "stop") {
|
|
63
65
|
const when = opening ? "at the start" : `after turn ${turnNumber}`;
|
|
@@ -13,7 +13,7 @@ export type ScreenshotRef = NonNullable<ActorTraceItem["screenshotRef"]>;
|
|
|
13
13
|
* wrapped callbacks are fields on LoopSession instead. Callers destructure hooks to call them.
|
|
14
14
|
*/
|
|
15
15
|
export type LoopSettings = {
|
|
16
|
-
readonly [K in "instructions" | "persona" | "redaction" | "stopWhen" | "dwell" | "clock" | "tasks" | "maxUsd" | "overRunBudget" | "estimateTurnCostUsd" | "onObservedUrl" | "onMessage" | "onScreenshot" | "onTrace" | "recordPages"]: LoopRunOptions[K];
|
|
16
|
+
readonly [K in "instructions" | "persona" | "redaction" | "stopWhen" | "dwell" | "clock" | "tasks" | "maxUsd" | "overRunBudget" | "estimateTurnCostUsd" | "onObservedUrl" | "onMessage" | "onScreenshot" | "onTrace" | "recordPages" | "onCheckpoint"]: LoopRunOptions[K];
|
|
17
17
|
};
|
|
18
18
|
/** The participant's dispatched actions, as the backstop and failure notices describe them. */
|
|
19
19
|
export interface ActionHistory {
|
|
@@ -72,9 +72,10 @@ export declare class LoopSession {
|
|
|
72
72
|
/** Set by the participant's own final account or by its closing report. */
|
|
73
73
|
impressions: ParticipantImpressions | undefined;
|
|
74
74
|
private stopCause;
|
|
75
|
-
private readonly
|
|
75
|
+
private readonly redactTrace;
|
|
76
76
|
constructor(options: LoopRunOptions);
|
|
77
77
|
remaining(): number;
|
|
78
|
+
/** Model-authored narration and recorded pages, through traceRedaction. */
|
|
78
79
|
redactNarration(text: string): string;
|
|
79
80
|
/** Hand a watcher the trace so far with the running usage, without waiting on it. */
|
|
80
81
|
flush(): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { traceRedaction } from "../../../evidence/trace-page.js";
|
|
2
2
|
import { TaskTracker } from "../../../study/tasks.js";
|
|
3
3
|
import { StreakRecord } from "./streak.js";
|
|
4
4
|
import { TraceRecorder } from "./trace.js";
|
|
@@ -73,10 +73,10 @@ export class LoopSession {
|
|
|
73
73
|
/** Set by the participant's own final account or by its closing report. */
|
|
74
74
|
impressions;
|
|
75
75
|
stopCause;
|
|
76
|
-
|
|
76
|
+
redactTrace;
|
|
77
77
|
constructor(options) {
|
|
78
78
|
// Read once, in this order: a caller mutating its options object mid-run changes nothing.
|
|
79
|
-
const { instructions, provider, executor, persona, redaction, timeoutMs, now, signal, idleSteps = DEFAULT_IDLE_STEPS, noProgressSteps = DEFAULT_NO_PROGRESS_STEPS, maxWaitMs, idleWaitMs, acknowledgeSafetyChecks = () => null, redactScreenshots = false, scrubText = (text) => text, writeScreenshot = async (name) => `screenshots/${name}`, stopWhen, dwell, clock, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), tasks, maxUsd, overRunBudget, estimateTurnCostUsd, requireReportedUsageForSpendCap = false, onObservedUrl, onMessage, onScreenshot, onTrace, recordPages, } = options;
|
|
79
|
+
const { instructions, provider, executor, persona, redaction, timeoutMs, now, signal, idleSteps = DEFAULT_IDLE_STEPS, noProgressSteps = DEFAULT_NO_PROGRESS_STEPS, maxWaitMs, idleWaitMs, acknowledgeSafetyChecks = () => null, redactScreenshots = false, scrubText = (text) => text, writeScreenshot = async (name) => `screenshots/${name}`, stopWhen, dwell, clock, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), tasks, maxUsd, overRunBudget, estimateTurnCostUsd, requireReportedUsageForSpendCap = false, onObservedUrl, onMessage, onScreenshot, onTrace, recordPages, onCheckpoint, } = options;
|
|
80
80
|
this.settings = {
|
|
81
81
|
instructions,
|
|
82
82
|
persona,
|
|
@@ -93,6 +93,7 @@ export class LoopSession {
|
|
|
93
93
|
onScreenshot,
|
|
94
94
|
onTrace,
|
|
95
95
|
recordPages,
|
|
96
|
+
onCheckpoint,
|
|
96
97
|
};
|
|
97
98
|
this.provider = provider;
|
|
98
99
|
this.executor = executor;
|
|
@@ -108,7 +109,8 @@ export class LoopSession {
|
|
|
108
109
|
this.redactScreenshots = redactScreenshots;
|
|
109
110
|
this.now = () => now();
|
|
110
111
|
this.acknowledgeSafetyChecks = (checks) => acknowledgeSafetyChecks(checks);
|
|
111
|
-
|
|
112
|
+
// The run's scrubKnownValues comes in as scrubText.
|
|
113
|
+
this.redactTrace = traceRedaction((text) => scrubText(text), (text) => redaction.redactText(text));
|
|
112
114
|
this.writeScreenshot = (name, bytes) => writeScreenshot(name, bytes);
|
|
113
115
|
this.sleep = (ms) => sleep(ms);
|
|
114
116
|
this.capDeclared = maxUsd !== undefined || overRunBudget !== undefined;
|
|
@@ -123,15 +125,9 @@ export class LoopSession {
|
|
|
123
125
|
remaining() {
|
|
124
126
|
return this.timeoutMs - (this.now() - this.startedAtMs);
|
|
125
127
|
}
|
|
126
|
-
|
|
127
|
-
// A value the model transcribes (a DB password it read on screen) has no shape, so redactText
|
|
128
|
-
// alone cannot catch it; the run's scrubKnownValues, injected as scrubText, closes that. The
|
|
129
|
-
// participant receives its instructions as written, so it can repeat a key the study wrote
|
|
130
|
-
// base64- or percent-encoded, which verify decodes; redactEncodedText removes that one too.
|
|
131
|
-
// The known values are scrubbed again last: a marker written before other text can spell one,
|
|
132
|
-
// as `[REDACTED_SECRET] and` spells `SECRET] and`.
|
|
128
|
+
/** Model-authored narration and recorded pages, through traceRedaction. */
|
|
133
129
|
redactNarration(text) {
|
|
134
|
-
return this.
|
|
130
|
+
return this.redactTrace(text);
|
|
135
131
|
}
|
|
136
132
|
/** Hand a watcher the trace so far with the running usage, without waiting on it. */
|
|
137
133
|
flush() {
|
|
@@ -484,7 +484,10 @@ export interface LoopTaps {
|
|
|
484
484
|
*/
|
|
485
485
|
onScreenshot?: (frame: Buffer) => void;
|
|
486
486
|
}
|
|
487
|
-
/**
|
|
487
|
+
/**
|
|
488
|
+
* The loop's options inside humanish: the public ones, the handoff's taps, the page switch and the
|
|
489
|
+
* checkpoint tap.
|
|
490
|
+
*/
|
|
488
491
|
export type LoopRunOptions = CuaLoopOptions & LoopTaps & {
|
|
489
492
|
/**
|
|
490
493
|
* Whether screenshot items and the trace carry the observed page (`page`, `finalPage`).
|
|
@@ -492,6 +495,16 @@ export type LoopRunOptions = CuaLoopOptions & LoopTaps & {
|
|
|
492
495
|
* as digests (docs/architecture/external-public-shared-world.md).
|
|
493
496
|
*/
|
|
494
497
|
recordPages?: boolean;
|
|
498
|
+
/**
|
|
499
|
+
* Runtime-only checkpoint tap: called with the turn's number after its checkpoint screenshot
|
|
500
|
+
* item (turn-03) is recorded, and again after its after-dwell item (turn-03-after-dwell),
|
|
501
|
+
* before the turn's stop checks. A held turn and a reply cut off by the output limit take no
|
|
502
|
+
* checkpoint, so they never reach it. Default: no-op.
|
|
503
|
+
*
|
|
504
|
+
* Built-in caller: the hosted E2B desktop pairs the number with the time of the browser-state
|
|
505
|
+
* read that screenshot came after, and its network log numbers requests by those pairs.
|
|
506
|
+
*/
|
|
507
|
+
onCheckpoint?: (turnNumber: number) => void;
|
|
495
508
|
};
|
|
496
509
|
export type CuaLiveMetadata = Pick<ActorTrace, "executionProfile" | "providerRequests" | "historyTurnsOmitted">;
|
|
497
510
|
/** What runComputerUseLoop returns; the public name for an actor session result. */
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export declare const BROWSER_NETWORK_SCHEMA = "humanish.browser-network.v1";
|
|
2
|
+
/** Why records are missing from a participant's network log, as the index's `reason` says. */
|
|
3
|
+
export declare const BROWSER_NETWORK_GAPS: readonly ["no-capture", "holder-stopped", "capped", "not-collected"];
|
|
4
|
+
type BrowserNetworkGap = (typeof BROWSER_NETWORK_GAPS)[number];
|
|
5
|
+
/** A stream's `network` field in run.json. */
|
|
6
|
+
export interface BrowserNetworkIndex {
|
|
7
|
+
schema: typeof BROWSER_NETWORK_SCHEMA;
|
|
8
|
+
/**
|
|
9
|
+
* network/<participant id>.ndjson, with the file's record count, byte count and sha256, and how
|
|
10
|
+
* many of its records failed and are pending. All six are absent when no file was written:
|
|
11
|
+
* capture did not start (`no-capture`), the events were not read (`not-collected`), or capture
|
|
12
|
+
* started and kept no record, which `startedAt` tells apart.
|
|
13
|
+
*/
|
|
14
|
+
path?: string;
|
|
15
|
+
records?: number;
|
|
16
|
+
/** Records with `failed`: requests that got no response or broke off. */
|
|
17
|
+
failed?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Records with `pending`: requests with no recorded end, still open when the file was read or
|
|
20
|
+
* when capture stopped (`capped`, `holder-stopped`).
|
|
21
|
+
*/
|
|
22
|
+
pending?: number;
|
|
23
|
+
bytes?: number;
|
|
24
|
+
sha256?: string;
|
|
25
|
+
/** When the launch page's Network domain answered, on the desktop's clock. */
|
|
26
|
+
startedAt?: string;
|
|
27
|
+
/** The origins whose requests are written, redacted as a trace page's origin is. */
|
|
28
|
+
origins: string[];
|
|
29
|
+
complete: boolean;
|
|
30
|
+
/** Present when `complete` is false. */
|
|
31
|
+
reason?: BrowserNetworkGap;
|
|
32
|
+
omitted: {
|
|
33
|
+
/** Requests to an origin outside `origins`. */
|
|
34
|
+
otherOrigin: number;
|
|
35
|
+
/**
|
|
36
|
+
* Records past the writer's caps, which are not checked. Requests after the holder's own cap
|
|
37
|
+
* (`capped` with no overCap) are not counted anywhere.
|
|
38
|
+
*/
|
|
39
|
+
overCap: number;
|
|
40
|
+
/** Records that failed the record check. */
|
|
41
|
+
invalid: number;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A checkpoint screenshot's browser-state read: `wallTime` is the read's clock in seconds since the
|
|
46
|
+
* epoch on the desktop, the clock the holder's request times use, and `turn` the screenshot's N.
|
|
47
|
+
*/
|
|
48
|
+
export interface TurnMark {
|
|
49
|
+
wallTime: number;
|
|
50
|
+
turn: number;
|
|
51
|
+
}
|
|
52
|
+
export interface BrowserNetworkCapture {
|
|
53
|
+
/** The participant's id, which names the file. */
|
|
54
|
+
participantId: string;
|
|
55
|
+
/** The origins whose requests are kept, as `new URL(url).origin` writes them. */
|
|
56
|
+
origins: readonly string[];
|
|
57
|
+
/** The holder's events file as the host read it, whole lines and possibly a last partial one. */
|
|
58
|
+
events: string;
|
|
59
|
+
/** The participant's checkpoint marks, in the order they were taken. */
|
|
60
|
+
marks: readonly TurnMark[];
|
|
61
|
+
/** The trace redaction the participant's pages went through (traceRedaction). */
|
|
62
|
+
redact: (text: string) => string;
|
|
63
|
+
/**
|
|
64
|
+
* The holder had exited before `events` was read. A holder killed by a signal writes no exit
|
|
65
|
+
* line, so without this the file reads as complete.
|
|
66
|
+
*/
|
|
67
|
+
holderExited?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* The participant's own sandbox id and those the run journaled. Run.finish rewrites a journaled
|
|
70
|
+
* id in every run file after run.json indexes them, so the writer withholds each path segment
|
|
71
|
+
* that names one, before any cut, and the sweep finds nothing to change.
|
|
72
|
+
*/
|
|
73
|
+
sandboxIds?: readonly string[];
|
|
74
|
+
}
|
|
75
|
+
export interface BrowserNetworkLog {
|
|
76
|
+
index: BrowserNetworkIndex;
|
|
77
|
+
/** The file's text, for `index.path`; absent when the index has no path. */
|
|
78
|
+
text?: string;
|
|
79
|
+
/** What a reader of the run should know about the log, such as records with no turn. */
|
|
80
|
+
warnings: string[];
|
|
81
|
+
}
|
|
82
|
+
/** Whether `value` is an ISO time as `Date.prototype.toISOString` writes one. */
|
|
83
|
+
export declare function isIsoTime(value: unknown): value is string;
|
|
84
|
+
/** The run-relative path of a participant's network log. */
|
|
85
|
+
export declare function networkLogPath(participantId: string): string;
|
|
86
|
+
/**
|
|
87
|
+
* What is wrong with one network log record, or undefined when it holds only the schema's keys and
|
|
88
|
+
* values. The writer leaves out a record this names; verify reports one as a finding. Never says
|
|
89
|
+
* what the record holds.
|
|
90
|
+
*/
|
|
91
|
+
export declare function networkRecordProblem(record: unknown): string | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* The index of a participant whose events were never read: capture did not start, or the file
|
|
94
|
+
* could not be read at teardown. No file goes with it.
|
|
95
|
+
*/
|
|
96
|
+
export declare function networkIndexWithoutEvents(capture: Pick<BrowserNetworkCapture, "origins" | "redact" | "sandboxIds">, reason: "no-capture" | "not-collected"): BrowserNetworkIndex;
|
|
97
|
+
/**
|
|
98
|
+
* The network log of one participant: the records the holder's events give, joined by request id
|
|
99
|
+
* into one per hop, redacted, tagged with turns, checked and capped, then the index that binds
|
|
100
|
+
* them. A redirect gives the 3xx hop's record, then one with `redirect: true`. A request's turn is
|
|
101
|
+
* the N of the first mark at or after its start, or the last mark's N plus 1 after every mark.
|
|
102
|
+
* Capture that started and kept no record writes no file. Only a hop the caps still take is
|
|
103
|
+
* redacted, and the work yields to the event loop every 20 ms, so the other participants of a
|
|
104
|
+
* fan-out keep running while a 32 MiB events file is reduced. Throws only for a participant id
|
|
105
|
+
* that is not one path segment.
|
|
106
|
+
*/
|
|
107
|
+
export declare function reduceBrowserNetwork(capture: BrowserNetworkCapture): Promise<BrowserNetworkLog>;
|
|
108
|
+
export {};
|