@descryy/mcp 0.2.0 → 0.4.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/dist/bin/descry-mcp.js +6 -1
- package/dist/bin/descry-mcp.js.map +1 -1
- package/dist/browser/driver.d.ts +236 -0
- package/dist/browser/driver.d.ts.map +1 -0
- package/dist/browser/driver.js +70 -0
- package/dist/browser/driver.js.map +1 -0
- package/dist/browser/evidence.d.ts +47 -0
- package/dist/browser/evidence.d.ts.map +1 -0
- package/dist/browser/evidence.js +55 -0
- package/dist/browser/evidence.js.map +1 -0
- package/dist/browser/fake-driver.d.ts +58 -0
- package/dist/browser/fake-driver.d.ts.map +1 -0
- package/dist/browser/fake-driver.js +161 -0
- package/dist/browser/fake-driver.js.map +1 -0
- package/dist/browser/graph-write.d.ts +86 -0
- package/dist/browser/graph-write.d.ts.map +1 -0
- package/dist/browser/graph-write.js +135 -0
- package/dist/browser/graph-write.js.map +1 -0
- package/dist/browser/playwright-driver.d.ts +65 -0
- package/dist/browser/playwright-driver.d.ts.map +1 -0
- package/dist/browser/playwright-driver.js +359 -0
- package/dist/browser/playwright-driver.js.map +1 -0
- package/dist/browser/provider.d.ts +49 -0
- package/dist/browser/provider.d.ts.map +1 -0
- package/dist/browser/provider.js +28 -0
- package/dist/browser/provider.js.map +1 -0
- package/dist/browser/registry.d.ts +182 -0
- package/dist/browser/registry.d.ts.map +1 -0
- package/dist/browser/registry.js +215 -0
- package/dist/browser/registry.js.map +1 -0
- package/dist/browser/scenario-resolve.d.ts +62 -0
- package/dist/browser/scenario-resolve.d.ts.map +1 -0
- package/dist/browser/scenario-resolve.js +127 -0
- package/dist/browser/scenario-resolve.js.map +1 -0
- package/dist/browser/scenario-runner.d.ts +113 -0
- package/dist/browser/scenario-runner.d.ts.map +1 -0
- package/dist/browser/scenario-runner.js +315 -0
- package/dist/browser/scenario-runner.js.map +1 -0
- package/dist/browser/stack-parser.d.ts +43 -0
- package/dist/browser/stack-parser.d.ts.map +1 -0
- package/dist/browser/stack-parser.js +112 -0
- package/dist/browser/stack-parser.js.map +1 -0
- package/dist/browser/tool-support.d.ts +113 -0
- package/dist/browser/tool-support.d.ts.map +1 -0
- package/dist/browser/tool-support.js +181 -0
- package/dist/browser/tool-support.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/render.d.ts +112 -10
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +79 -13
- package/dist/render.js.map +1 -1
- package/dist/scenarios/index.d.ts +4 -0
- package/dist/scenarios/index.d.ts.map +1 -0
- package/dist/scenarios/index.js +4 -0
- package/dist/scenarios/index.js.map +1 -0
- package/dist/scenarios/parse.d.ts +32 -0
- package/dist/scenarios/parse.d.ts.map +1 -0
- package/dist/scenarios/parse.js +199 -0
- package/dist/scenarios/parse.js.map +1 -0
- package/dist/scenarios/scenario.d.ts +115 -0
- package/dist/scenarios/scenario.d.ts.map +1 -0
- package/dist/scenarios/scenario.js +41 -0
- package/dist/scenarios/scenario.js.map +1 -0
- package/dist/scenarios/storage.d.ts +51 -0
- package/dist/scenarios/storage.d.ts.map +1 -0
- package/dist/scenarios/storage.js +93 -0
- package/dist/scenarios/storage.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +6 -3
- package/dist/server.js.map +1 -1
- package/dist/session.d.ts +68 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +89 -0
- package/dist/session.js.map +1 -1
- package/dist/tools/analyze.d.ts +41 -1
- package/dist/tools/analyze.d.ts.map +1 -1
- package/dist/tools/analyze.js +81 -8
- package/dist/tools/analyze.js.map +1 -1
- package/dist/tools/browser-click.d.ts +36 -0
- package/dist/tools/browser-click.d.ts.map +1 -0
- package/dist/tools/browser-click.js +117 -0
- package/dist/tools/browser-click.js.map +1 -0
- package/dist/tools/browser-close-session.d.ts +24 -0
- package/dist/tools/browser-close-session.d.ts.map +1 -0
- package/dist/tools/browser-close-session.js +63 -0
- package/dist/tools/browser-close-session.js.map +1 -0
- package/dist/tools/browser-fill.d.ts +49 -0
- package/dist/tools/browser-fill.d.ts.map +1 -0
- package/dist/tools/browser-fill.js +138 -0
- package/dist/tools/browser-fill.js.map +1 -0
- package/dist/tools/browser-navigate.d.ts +32 -0
- package/dist/tools/browser-navigate.d.ts.map +1 -0
- package/dist/tools/browser-navigate.js +103 -0
- package/dist/tools/browser-navigate.js.map +1 -0
- package/dist/tools/browser-run-scenario.d.ts +54 -0
- package/dist/tools/browser-run-scenario.d.ts.map +1 -0
- package/dist/tools/browser-run-scenario.js +228 -0
- package/dist/tools/browser-run-scenario.js.map +1 -0
- package/dist/tools/browser-save-scenario.d.ts +44 -0
- package/dist/tools/browser-save-scenario.d.ts.map +1 -0
- package/dist/tools/browser-save-scenario.js +298 -0
- package/dist/tools/browser-save-scenario.js.map +1 -0
- package/dist/tools/browser-snapshot.d.ts +60 -0
- package/dist/tools/browser-snapshot.d.ts.map +1 -0
- package/dist/tools/browser-snapshot.js +139 -0
- package/dist/tools/browser-snapshot.js.map +1 -0
- package/dist/tools/browser-start-session.d.ts +43 -0
- package/dist/tools/browser-start-session.d.ts.map +1 -0
- package/dist/tools/browser-start-session.js +272 -0
- package/dist/tools/browser-start-session.js.map +1 -0
- package/dist/tools/browser-type.d.ts +48 -0
- package/dist/tools/browser-type.d.ts.map +1 -0
- package/dist/tools/browser-type.js +136 -0
- package/dist/tools/browser-type.js.map +1 -0
- package/dist/tools/contracts.d.ts +15 -0
- package/dist/tools/contracts.d.ts.map +1 -1
- package/dist/tools/contracts.js +14 -3
- package/dist/tools/contracts.js.map +1 -1
- package/dist/tools/git-diff.d.ts.map +1 -1
- package/dist/tools/git-diff.js +85 -6
- package/dist/tools/git-diff.js.map +1 -1
- package/dist/tools/impact.d.ts +9 -0
- package/dist/tools/impact.d.ts.map +1 -1
- package/dist/tools/impact.js +3 -3
- package/dist/tools/impact.js.map +1 -1
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +27 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/kit.d.ts +10 -1
- package/dist/tools/kit.d.ts.map +1 -1
- package/dist/tools/kit.js +2 -0
- package/dist/tools/kit.js.map +1 -1
- package/dist/tools/observe-runtime.d.ts +113 -19
- package/dist/tools/observe-runtime.d.ts.map +1 -1
- package/dist/tools/observe-runtime.js +324 -53
- package/dist/tools/observe-runtime.js.map +1 -1
- package/dist/tools/observe-tests.d.ts +125 -0
- package/dist/tools/observe-tests.d.ts.map +1 -0
- package/dist/tools/observe-tests.js +313 -0
- package/dist/tools/observe-tests.js.map +1 -0
- package/dist/tools/pr-analysis.d.ts +11 -0
- package/dist/tools/pr-analysis.d.ts.map +1 -1
- package/dist/tools/pr-analysis.js +3 -3
- package/dist/tools/pr-analysis.js.map +1 -1
- package/dist/tools/pre-push.d.ts +77 -0
- package/dist/tools/pre-push.d.ts.map +1 -0
- package/dist/tools/pre-push.js +250 -0
- package/dist/tools/pre-push.js.map +1 -0
- package/dist/tools/questions.d.ts.map +1 -1
- package/dist/tools/questions.js +41 -16
- package/dist/tools/questions.js.map +1 -1
- package/dist/tools/verification-status.d.ts +22 -0
- package/dist/tools/verification-status.d.ts.map +1 -1
- package/dist/tools/verification-status.js +51 -5
- package/dist/tools/verification-status.js.map +1 -1
- package/package.json +14 -13
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The real `BrowserDriver`, over `@descryy/runtime-browser`.
|
|
3
|
+
*
|
|
4
|
+
* ## Why the import is dynamic
|
|
5
|
+
*
|
|
6
|
+
* `@descryy/runtime-browser` is not on the npm registry yet
|
|
7
|
+
* (`mcp-browser-tools.md` §3.1 — the publish returns 429 on new-scoped-package
|
|
8
|
+
* creation). Declaring it in `package.json` today would break `npm install`
|
|
9
|
+
* for everyone, including the lanes that never touch a browser. So it is
|
|
10
|
+
* imported by specifier at call time and its absence is a **named refusal
|
|
11
|
+
* with a remedy**, exactly as a missing Chromium is.
|
|
12
|
+
*
|
|
13
|
+
* That is a temporary shape and it is written down as one: the final swap
|
|
14
|
+
* (§8's tool-count item) declares the dependency and makes this a static
|
|
15
|
+
* import. What must *not* happen in the meantime is the tools quietly
|
|
16
|
+
* appearing to work — see `provider.ts`.
|
|
17
|
+
*
|
|
18
|
+
* ## What this adds over the runtime package, and what it deliberately does not
|
|
19
|
+
*
|
|
20
|
+
* It adds exactly one thing the runtime has no API for: **element refs.** The
|
|
21
|
+
* port's contract is that an action names an element the agent has seen, and
|
|
22
|
+
* `BrowserActionCollector` acts on raw selectors. So this module enumerates
|
|
23
|
+
* the page's interactive elements, holds a Playwright `ElementHandle` per ref,
|
|
24
|
+
* and drops the whole map on navigation. Handles rather than injected `data-`
|
|
25
|
+
* attributes on purpose: stamping the DOM would make the act of observing
|
|
26
|
+
* change the page being observed, and a detached element then fails naturally
|
|
27
|
+
* instead of resolving to whatever took its place.
|
|
28
|
+
*
|
|
29
|
+
* Everything else is composition. Launch, click, type, fill, console capture,
|
|
30
|
+
* network capture, the `fetch()` initiator stack and its source-map rewrite
|
|
31
|
+
* are all the runtime package's, called rather than reimplemented.
|
|
32
|
+
*
|
|
33
|
+
* ## Rule 1
|
|
34
|
+
*
|
|
35
|
+
* No language is named here. The stack-trace parser that turns a raw browser
|
|
36
|
+
* stack into resolved frames is handed in by the caller as a module specifier
|
|
37
|
+
* — the same mechanism `runtime-registry.ts` uses for runtime adapters, for
|
|
38
|
+
* the same reason. Without one, requests are still observed and no caller
|
|
39
|
+
* edge is written; the reply says so.
|
|
40
|
+
*/
|
|
41
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
42
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
43
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
44
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return path;
|
|
48
|
+
};
|
|
49
|
+
import { BrowserSessionCrashedError, UnknownElementRefError } from "./driver.js";
|
|
50
|
+
/** The module the driver composes. Named once, imported at call time. */
|
|
51
|
+
const RUNTIME_BROWSER_MODULE = "@descryy/runtime-browser";
|
|
52
|
+
/**
|
|
53
|
+
* Elements an agent can act on.
|
|
54
|
+
*
|
|
55
|
+
* Deliberately narrow. A snapshot of every node on the page would be
|
|
56
|
+
* enormous, mostly unactionable, and would push the reply budget into
|
|
57
|
+
* dropping the elements that matter. `[role]` is included so an application
|
|
58
|
+
* that builds its own controls is not invisible.
|
|
59
|
+
*/
|
|
60
|
+
const INTERACTIVE = "a, button, input, select, textarea, [role], [onclick], summary";
|
|
61
|
+
export class BrowserBackendMissingError extends Error {
|
|
62
|
+
constructor(cause) {
|
|
63
|
+
super(`Could not load ${RUNTIME_BROWSER_MODULE}: ${cause instanceof Error ? cause.message : String(cause)}. ` +
|
|
64
|
+
"This build of @descryy/mcp does not have the browser backend installed.");
|
|
65
|
+
this.name = "BrowserBackendMissingError";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export async function createPlaywrightBrowserDriver(options = {}) {
|
|
69
|
+
let runtime;
|
|
70
|
+
try {
|
|
71
|
+
runtime = (await import(__rewriteRelativeImportExtension(RUNTIME_BROWSER_MODULE)));
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
throw new BrowserBackendMissingError(error);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
async launch(launchOptions) {
|
|
78
|
+
const launch = await runtime.launchBrowserSessionOrRefuse({ headless: launchOptions.headless ?? true });
|
|
79
|
+
if (!launch.launched) {
|
|
80
|
+
const { launched: _launched, ...refusal } = launch;
|
|
81
|
+
return { launched: false, ...refusal };
|
|
82
|
+
}
|
|
83
|
+
const session = await openSession(runtime, launch.session, launchOptions, options);
|
|
84
|
+
return { launched: true, session };
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async function openSession(runtime, session, launchOptions, options) {
|
|
89
|
+
const emitted = [];
|
|
90
|
+
const actions = [];
|
|
91
|
+
let refs = new Map();
|
|
92
|
+
let generation = 0;
|
|
93
|
+
let closed = false;
|
|
94
|
+
let finalObservation = null;
|
|
95
|
+
const context = {
|
|
96
|
+
executionId: `mcp-browser-${session.sessionId}`,
|
|
97
|
+
configuration: { environmentTier: "tier-2-container", fidelityLevel: 2, timeoutMs: 30_000, services: {} },
|
|
98
|
+
emit: (evidence) => {
|
|
99
|
+
emitted.push(evidence);
|
|
100
|
+
},
|
|
101
|
+
...(options.resolveSourceRoot === undefined ? {} : { resolveSourceRoot: options.resolveSourceRoot }),
|
|
102
|
+
};
|
|
103
|
+
const actionCollector = runtime.createBrowserActionCollector({
|
|
104
|
+
session,
|
|
105
|
+
...(options.service === undefined ? {} : { service: options.service }),
|
|
106
|
+
});
|
|
107
|
+
const consoleCollector = runtime.createBrowserConsoleCollector({
|
|
108
|
+
session,
|
|
109
|
+
...(options.service === undefined ? {} : { service: options.service }),
|
|
110
|
+
...(options.stackParser === undefined ? {} : { stackTraceParser: options.stackParser }),
|
|
111
|
+
});
|
|
112
|
+
const networkCollector = runtime.createBrowserNetworkCollector({
|
|
113
|
+
session,
|
|
114
|
+
...(options.service === undefined ? {} : { service: options.service }),
|
|
115
|
+
...(options.stackParser === undefined ? {} : { stackTraceParser: options.stackParser }),
|
|
116
|
+
});
|
|
117
|
+
// Started before the first navigation, deliberately. The initiator capture
|
|
118
|
+
// wraps `fetch` via an init script, and Playwright's own contract is that
|
|
119
|
+
// an init script does not reach a document already loaded — so a collector
|
|
120
|
+
// started after navigating would observe a page it could never have
|
|
121
|
+
// instrumented, and would report an honest-looking empty stack for every
|
|
122
|
+
// request.
|
|
123
|
+
await actionCollector.start(context);
|
|
124
|
+
await consoleCollector.start(context);
|
|
125
|
+
await networkCollector.start(context);
|
|
126
|
+
await actionCollector.navigate(launchOptions.targetUrl);
|
|
127
|
+
function assertUsable() {
|
|
128
|
+
if (closed || !session.isUsable())
|
|
129
|
+
throw new BrowserSessionCrashedError(session.sessionId);
|
|
130
|
+
}
|
|
131
|
+
function resolve(ref) {
|
|
132
|
+
const found = refs.get(ref);
|
|
133
|
+
if (found === undefined)
|
|
134
|
+
throw new UnknownElementRefError(ref);
|
|
135
|
+
return found;
|
|
136
|
+
}
|
|
137
|
+
function recordAction(action, ref, mode) {
|
|
138
|
+
actions.push({ action, ref, mode, url: session.page.url(), at: new Date().toISOString() });
|
|
139
|
+
}
|
|
140
|
+
async function dropRefs() {
|
|
141
|
+
const handles = [...refs.values()].map((r) => r.handle);
|
|
142
|
+
refs = new Map();
|
|
143
|
+
await Promise.all(handles.map((h) => h.dispose().catch(() => { })));
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
sessionId: session.sessionId,
|
|
147
|
+
startedAt: session.startedAt,
|
|
148
|
+
isUsable: () => !closed && session.isUsable(),
|
|
149
|
+
currentUrl: () => session.page.url(),
|
|
150
|
+
async navigate(url) {
|
|
151
|
+
assertUsable();
|
|
152
|
+
await dropRefs();
|
|
153
|
+
await actionCollector.navigate(url);
|
|
154
|
+
recordAction("navigate", null, null);
|
|
155
|
+
},
|
|
156
|
+
async snapshot() {
|
|
157
|
+
assertUsable();
|
|
158
|
+
await dropRefs();
|
|
159
|
+
generation += 1;
|
|
160
|
+
const handles = await session.page.$$(INTERACTIVE);
|
|
161
|
+
const elements = [];
|
|
162
|
+
for (const [index, handle] of handles.entries()) {
|
|
163
|
+
const described = await handle
|
|
164
|
+
.evaluate((el) => {
|
|
165
|
+
const tag = el.tagName.toLowerCase();
|
|
166
|
+
const explicit = el.getAttribute("role");
|
|
167
|
+
const type = el.getAttribute("type");
|
|
168
|
+
const role = explicit ??
|
|
169
|
+
(tag === "a"
|
|
170
|
+
? "link"
|
|
171
|
+
: tag === "button" || (tag === "input" && (type === "button" || type === "submit"))
|
|
172
|
+
? "button"
|
|
173
|
+
: tag === "select"
|
|
174
|
+
? "combobox"
|
|
175
|
+
: tag === "textarea" || (tag === "input" && (type === null || type === "text" || type === "search"))
|
|
176
|
+
? "textbox"
|
|
177
|
+
: tag === "input" && type === "checkbox"
|
|
178
|
+
? "checkbox"
|
|
179
|
+
: tag);
|
|
180
|
+
// A pragmatic accessible name, not a full AccName implementation:
|
|
181
|
+
// the label a person would read, in the order a person would find
|
|
182
|
+
// it. Named as an approximation rather than presented as the
|
|
183
|
+
// accessibility tree's own answer.
|
|
184
|
+
const name = el.getAttribute("aria-label") ??
|
|
185
|
+
el.innerText?.trim() ??
|
|
186
|
+
el.textContent?.trim() ??
|
|
187
|
+
el.getAttribute("placeholder") ??
|
|
188
|
+
el.getAttribute("name") ??
|
|
189
|
+
"";
|
|
190
|
+
return { role, name: name.slice(0, 200) };
|
|
191
|
+
})
|
|
192
|
+
.catch(() => null);
|
|
193
|
+
if (described === null) {
|
|
194
|
+
await handle.dispose().catch(() => { });
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const ref = `ref-${generation}-${index}`;
|
|
198
|
+
const element = {
|
|
199
|
+
ref,
|
|
200
|
+
role: described.role,
|
|
201
|
+
name: described.name,
|
|
202
|
+
// Honest: this driver acts through a held handle, not through a
|
|
203
|
+
// selector string. Reporting a fabricated CSS path here would be a
|
|
204
|
+
// selector nothing ever uses and that might not even match.
|
|
205
|
+
selector: `(held handle ${ref})`,
|
|
206
|
+
};
|
|
207
|
+
refs.set(ref, { element, handle });
|
|
208
|
+
elements.push(element);
|
|
209
|
+
}
|
|
210
|
+
return { url: session.page.url(), title: await session.page.title().catch(() => ""), elements, totalElements: elements.length };
|
|
211
|
+
},
|
|
212
|
+
async click(ref) {
|
|
213
|
+
assertUsable();
|
|
214
|
+
await resolve(ref).handle.click();
|
|
215
|
+
recordAction("click", ref, null);
|
|
216
|
+
// `requestfinished` fires after the page's own handler resolves, so a
|
|
217
|
+
// drain immediately after a click would miss the request the click
|
|
218
|
+
// caused — which is the request this whole feature exists to witness.
|
|
219
|
+
await session.page.waitForTimeout(300);
|
|
220
|
+
},
|
|
221
|
+
async type(ref, text) {
|
|
222
|
+
assertUsable();
|
|
223
|
+
const { handle } = resolve(ref);
|
|
224
|
+
if (handle.pressSequentially !== undefined)
|
|
225
|
+
await handle.pressSequentially(text);
|
|
226
|
+
else if (handle.type !== undefined)
|
|
227
|
+
await handle.type(text);
|
|
228
|
+
else
|
|
229
|
+
throw new Error("this Playwright build exposes no keystroke-level typing method");
|
|
230
|
+
recordAction("type", ref, "append");
|
|
231
|
+
await session.page.waitForTimeout(300);
|
|
232
|
+
},
|
|
233
|
+
async fill(ref, text) {
|
|
234
|
+
assertUsable();
|
|
235
|
+
await resolve(ref).handle.fill(text);
|
|
236
|
+
recordAction("fill", ref, "replace");
|
|
237
|
+
await session.page.waitForTimeout(300);
|
|
238
|
+
},
|
|
239
|
+
async drainEvidence() {
|
|
240
|
+
const observation = collect(emitted, actions);
|
|
241
|
+
emitted.length = 0;
|
|
242
|
+
actions.length = 0;
|
|
243
|
+
return observation;
|
|
244
|
+
},
|
|
245
|
+
async close() {
|
|
246
|
+
if (finalObservation !== null)
|
|
247
|
+
return finalObservation;
|
|
248
|
+
closed = true;
|
|
249
|
+
// Collectors are stopped before the observation is taken: a stop
|
|
250
|
+
// flushes whatever the collector was still holding, and taking the
|
|
251
|
+
// observation first would drop exactly that.
|
|
252
|
+
await actionCollector.stop().catch(() => { });
|
|
253
|
+
await consoleCollector.stop().catch(() => { });
|
|
254
|
+
await networkCollector.stop().catch(() => { });
|
|
255
|
+
const observation = collect(emitted, actions);
|
|
256
|
+
emitted.length = 0;
|
|
257
|
+
actions.length = 0;
|
|
258
|
+
await dropRefs();
|
|
259
|
+
await session.close().catch(() => { });
|
|
260
|
+
finalObservation = observation;
|
|
261
|
+
return observation;
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Turn what the collectors emitted into the port's vocabulary.
|
|
267
|
+
*
|
|
268
|
+
* The request/response join is on `requestId`, because a `NETWORK_REQUEST`
|
|
269
|
+
* carries the method, the URL and the call-site stack while only the matching
|
|
270
|
+
* `NETWORK_RESPONSE` knows the status. A request with no response is kept with
|
|
271
|
+
* `status: null` — "never answered" is a different fact from a 500, and the
|
|
272
|
+
* port says so.
|
|
273
|
+
*/
|
|
274
|
+
function collect(emitted, actions) {
|
|
275
|
+
// Two joins, in priority order, because `requestId` is a *correlation
|
|
276
|
+
// header* and not a transport id: it exists only when the application
|
|
277
|
+
// itself propagates one. The fixture's own delete sets `x-request-id`, so
|
|
278
|
+
// an id-only join looked correct while silently reporting `status: null`
|
|
279
|
+
// for every request the page issued without one — which is most of them.
|
|
280
|
+
const statusByRequestId = new Map();
|
|
281
|
+
const statusByUrl = new Map();
|
|
282
|
+
for (const evidence of emitted) {
|
|
283
|
+
if (evidence.eventType !== "NETWORK_RESPONSE")
|
|
284
|
+
continue;
|
|
285
|
+
const status = evidence.payload["status"];
|
|
286
|
+
if (typeof status !== "number")
|
|
287
|
+
continue;
|
|
288
|
+
if (evidence.requestId !== null)
|
|
289
|
+
statusByRequestId.set(evidence.requestId, status);
|
|
290
|
+
const url = evidence.payload["url"];
|
|
291
|
+
// Last response wins: a page that requests the same URL twice reports the
|
|
292
|
+
// most recent outcome, which is the one a caller reading this reply is
|
|
293
|
+
// asking about.
|
|
294
|
+
if (typeof url === "string")
|
|
295
|
+
statusByUrl.set(url, status);
|
|
296
|
+
}
|
|
297
|
+
const requests = [];
|
|
298
|
+
const consoleErrors = [];
|
|
299
|
+
for (const evidence of emitted) {
|
|
300
|
+
if (evidence.eventType === "NETWORK_REQUEST") {
|
|
301
|
+
const method = evidence.payload["method"];
|
|
302
|
+
const url = evidence.payload["url"];
|
|
303
|
+
if (typeof method !== "string" || typeof url !== "string")
|
|
304
|
+
continue;
|
|
305
|
+
requests.push({
|
|
306
|
+
method,
|
|
307
|
+
url,
|
|
308
|
+
status: (evidence.requestId === null ? undefined : statusByRequestId.get(evidence.requestId)) ??
|
|
309
|
+
statusByUrl.get(url) ??
|
|
310
|
+
null,
|
|
311
|
+
stackText: renderStack(evidence.stackTrace),
|
|
312
|
+
stackTrace: evidence.stackTrace,
|
|
313
|
+
at: evidence.timestamp,
|
|
314
|
+
});
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
// An uncaught page error and a console error are both "the page reported
|
|
318
|
+
// something went wrong"; a caller triaging them does not need to know
|
|
319
|
+
// which listener fired.
|
|
320
|
+
if (evidence.eventType === "EXCEPTION" || evidence.eventType === "CONSOLE_MESSAGE") {
|
|
321
|
+
const level = evidence.payload["level"] ?? evidence.payload["type"];
|
|
322
|
+
if (evidence.eventType === "CONSOLE_MESSAGE" && level !== "error")
|
|
323
|
+
continue;
|
|
324
|
+
const text = evidence.payload["text"] ?? evidence.payload["message"];
|
|
325
|
+
consoleErrors.push({
|
|
326
|
+
text: typeof text === "string" ? text : JSON.stringify(evidence.payload),
|
|
327
|
+
stackText: renderStack(evidence.stackTrace),
|
|
328
|
+
at: evidence.timestamp,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return { actions: [...actions], consoleErrors, requests };
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* A short, readable rendering of a parsed stack.
|
|
336
|
+
*
|
|
337
|
+
* `StackTrace` carries frames, not the original text — the raw string is
|
|
338
|
+
* consumed by the parser and deliberately not kept, since a parsed frame with
|
|
339
|
+
* a resolved on-disk path is strictly more useful than the `http://` line it
|
|
340
|
+
* came from. So the port's `stackText` is rendered from the frames rather
|
|
341
|
+
* than passed through, and it is for a human reading the reply: the R4 write
|
|
342
|
+
* uses `stackTrace`, never this.
|
|
343
|
+
*
|
|
344
|
+
* The primary frame is marked, because it is the one a developer should be
|
|
345
|
+
* sent to and it is not always the innermost.
|
|
346
|
+
*/
|
|
347
|
+
function renderStack(stack) {
|
|
348
|
+
if (stack === null || stack.frames.length === 0)
|
|
349
|
+
return null;
|
|
350
|
+
return stack.frames
|
|
351
|
+
.slice(0, 5)
|
|
352
|
+
.map((frame, index) => {
|
|
353
|
+
const where = `${frame.location.file}:${frame.location.line}`;
|
|
354
|
+
const name = frame.location.functionName ?? "(anonymous)";
|
|
355
|
+
return `${index === stack.primaryFrameIndex ? "> " : " "}at ${name} (${where})`;
|
|
356
|
+
})
|
|
357
|
+
.join("\n");
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=playwright-driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-driver.js","sourceRoot":"","sources":["../../src/browser/playwright-driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a tool gets a browser.
|
|
3
|
+
*
|
|
4
|
+
* `@descryy/runtime-browser` is not on the registry yet (§3.1), so this build
|
|
5
|
+
* has no real driver in it. That absence is handled the way this codebase
|
|
6
|
+
* handles every expected inability: as a **named refusal with a remedy**,
|
|
7
|
+
* returned rather than thrown, and never as a tool that quietly does nothing.
|
|
8
|
+
*
|
|
9
|
+
* Rule 7 is the whole point of this file. A browser tool in a build with no
|
|
10
|
+
* browser backend must say *"this build cannot do that, and here is why"* —
|
|
11
|
+
* not fail obscurely inside a missing import, and certainly not return an
|
|
12
|
+
* empty snapshot that reads like a page with no elements on it.
|
|
13
|
+
*/
|
|
14
|
+
import type { StackTraceParser } from "@descryy/runtime-backend-observation";
|
|
15
|
+
import type { ServiceRootLookup } from "@descryy/runtime-contracts";
|
|
16
|
+
import type { BrowserDriver } from "./driver.ts";
|
|
17
|
+
/**
|
|
18
|
+
* Builds the driver one session will use.
|
|
19
|
+
*
|
|
20
|
+
* Takes the per-session facts a driver cannot know for itself: which parser
|
|
21
|
+
* can read this application's stack traces, and which on-disk root serves the
|
|
22
|
+
* origin being driven. Both are the caller's to state — see
|
|
23
|
+
* `stack-parser.ts` for why the parser cannot be chosen here, and
|
|
24
|
+
* `browser_start_session`'s `documentRoot` for why the root cannot be
|
|
25
|
+
* guessed.
|
|
26
|
+
*/
|
|
27
|
+
export type BrowserDriverFactory = (options: {
|
|
28
|
+
readonly stackParser?: StackTraceParser;
|
|
29
|
+
readonly resolveSourceRoot?: (origin: string) => ServiceRootLookup;
|
|
30
|
+
readonly service?: string;
|
|
31
|
+
}) => Promise<BrowserDriver>;
|
|
32
|
+
export interface BrowserBackendUnavailable {
|
|
33
|
+
readonly available: false;
|
|
34
|
+
readonly reason: string;
|
|
35
|
+
readonly remedy: string;
|
|
36
|
+
}
|
|
37
|
+
export type BrowserBackend = {
|
|
38
|
+
readonly available: true;
|
|
39
|
+
readonly createDriver: BrowserDriverFactory;
|
|
40
|
+
} | BrowserBackendUnavailable;
|
|
41
|
+
/**
|
|
42
|
+
* The stand-in used until the real driver is wired at the final swap.
|
|
43
|
+
*
|
|
44
|
+
* Deliberately not a driver that launches nothing successfully — that would
|
|
45
|
+
* make every browser tool return a plausible, empty, wrong answer. It is an
|
|
46
|
+
* explicit unavailability instead.
|
|
47
|
+
*/
|
|
48
|
+
export declare const BROWSER_BACKEND_NOT_INSTALLED: BrowserBackendUnavailable;
|
|
49
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/browser/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;;;GASG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC;IACxC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,iBAAiB,CAAC;IACnE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AAE7B,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAA;CAAE,GAAG,yBAAyB,CAAC;AAEnI;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,EAAE,yBAO3C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a tool gets a browser.
|
|
3
|
+
*
|
|
4
|
+
* `@descryy/runtime-browser` is not on the registry yet (§3.1), so this build
|
|
5
|
+
* has no real driver in it. That absence is handled the way this codebase
|
|
6
|
+
* handles every expected inability: as a **named refusal with a remedy**,
|
|
7
|
+
* returned rather than thrown, and never as a tool that quietly does nothing.
|
|
8
|
+
*
|
|
9
|
+
* Rule 7 is the whole point of this file. A browser tool in a build with no
|
|
10
|
+
* browser backend must say *"this build cannot do that, and here is why"* —
|
|
11
|
+
* not fail obscurely inside a missing import, and certainly not return an
|
|
12
|
+
* empty snapshot that reads like a page with no elements on it.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* The stand-in used until the real driver is wired at the final swap.
|
|
16
|
+
*
|
|
17
|
+
* Deliberately not a driver that launches nothing successfully — that would
|
|
18
|
+
* make every browser tool return a plausible, empty, wrong answer. It is an
|
|
19
|
+
* explicit unavailability instead.
|
|
20
|
+
*/
|
|
21
|
+
export const BROWSER_BACKEND_NOT_INSTALLED = {
|
|
22
|
+
available: false,
|
|
23
|
+
reason: "This build of @descryy/mcp has no browser backend. The browser tools are declared so a caller can see " +
|
|
24
|
+
"they exist and what they would need, but nothing in this build can drive a page — @descryy/runtime-browser " +
|
|
25
|
+
"is not yet part of the installed closure.",
|
|
26
|
+
remedy: "Install a build of @descryy/mcp that depends on @descryy/runtime-browser.",
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/browser/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA+BH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAA8B;IACtE,SAAS,EAAE,KAAK;IAChB,MAAM,EACJ,wGAAwG;QACxG,6GAA6G;QAC7G,2CAA2C;IAC7C,MAAM,EAAE,2EAA2E;CACpF,CAAC"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live browser sessions belonging to one connection — `mcp-browser-tools.md`
|
|
3
|
+
* §4.
|
|
4
|
+
*
|
|
5
|
+
* ## Why this is the hard part
|
|
6
|
+
*
|
|
7
|
+
* Every other tool on this surface is one-shot. It opens what it needs,
|
|
8
|
+
* answers, and holds nothing; a crash in the middle costs the caller one
|
|
9
|
+
* reply. A browser process that outlives a call is a different shape
|
|
10
|
+
* entirely, and the failure it introduces is not "a call fails" but "a
|
|
11
|
+
* process is still running on the developer's machine an hour after the
|
|
12
|
+
* agent stopped caring about it".
|
|
13
|
+
*
|
|
14
|
+
* So the design rule here is that **there is no path on which a session stops
|
|
15
|
+
* being tracked without its browser being closed and its evidence being
|
|
16
|
+
* handed back**. Four paths reach that state — idle timeout, client
|
|
17
|
+
* disconnect, crash, explicit close — and they converge on one private
|
|
18
|
+
* function, `reap`, rather than each doing their own teardown. They were four
|
|
19
|
+
* separate implementations in the first draft and the evidence flush was
|
|
20
|
+
* correct on three of them.
|
|
21
|
+
*
|
|
22
|
+
* ## Evidence is held, not dropped, and not silently discarded either
|
|
23
|
+
*
|
|
24
|
+
* A timeout or a disconnect has no reply to attach evidence to. Discarding it
|
|
25
|
+
* would be the failure rule 7 names — silently doing less — so a reaped
|
|
26
|
+
* session leaves a `ReapedSession` record behind carrying the reason and the
|
|
27
|
+
* final flush, and the next caller who names that id receives it instead of a
|
|
28
|
+
* bare "unknown session". That record is what turns "your session vanished"
|
|
29
|
+
* into "your session was idle for five minutes; here is what it saw before it
|
|
30
|
+
* went".
|
|
31
|
+
*
|
|
32
|
+
* ## Per connection, never global
|
|
33
|
+
*
|
|
34
|
+
* A registry is created per `Session`, which is created per connection. A
|
|
35
|
+
* global one would let a second client `use` a first client's browser by
|
|
36
|
+
* guessing a uuid, and would make the disconnect reap ambiguous about whose
|
|
37
|
+
* sessions it was reaping.
|
|
38
|
+
*/
|
|
39
|
+
import type { BrowserDriver, BrowserLaunchOptions, BrowserObservation, BrowserPageSession, ChromiumRefusal } from "./driver.ts";
|
|
40
|
+
/**
|
|
41
|
+
* How long a session may go untouched before it is torn down.
|
|
42
|
+
*
|
|
43
|
+
* A starting value, not a measurement, in this repo's usual sense: no agent
|
|
44
|
+
* has yet been observed pausing mid-exploration, so there is nothing to fit
|
|
45
|
+
* it to. Five minutes is long enough to survive a model thinking, short
|
|
46
|
+
* enough that a forgotten browser is a five-minute leak rather than an
|
|
47
|
+
* overnight one. It is deliberately the same figure as the action handshake's
|
|
48
|
+
* token TTL — an agent that cannot decide within one is unlikely to be coming
|
|
49
|
+
* back for the other.
|
|
50
|
+
*/
|
|
51
|
+
export declare const BROWSER_IDLE_TIMEOUT_MS: number;
|
|
52
|
+
/**
|
|
53
|
+
* How many sessions one connection may hold open at once.
|
|
54
|
+
*
|
|
55
|
+
* Small on purpose. A calling agent driving more than a couple of browsers
|
|
56
|
+
* simultaneously is not doing something this surface was built for, and each
|
|
57
|
+
* one is a real Chromium. Three leaves room for the honest case — a
|
|
58
|
+
* comparison between two states, plus one being opened — without letting a
|
|
59
|
+
* loop with a missing `browser_close_session` fill the machine.
|
|
60
|
+
*/
|
|
61
|
+
export declare const MAX_BROWSER_SESSIONS = 3;
|
|
62
|
+
export type ReapReason = "idleTimeout" | "clientDisconnect" | "crashed" | "closed";
|
|
63
|
+
/**
|
|
64
|
+
* DEC-270's vocabulary, read here and defined nowhere near here.
|
|
65
|
+
*
|
|
66
|
+
* A browser session's safety level is the environment profile's — the same
|
|
67
|
+
* field `observe_runtime` already reads. Declaring a second, browser-only
|
|
68
|
+
* notion of "safe" is how a runtime run and a browser run end up disagreeing
|
|
69
|
+
* about the same environment, which is the failure item 27 exists to prevent.
|
|
70
|
+
* Null means no profile was supplied, in which case the session's consent is
|
|
71
|
+
* the only authorization and it governs alone.
|
|
72
|
+
*/
|
|
73
|
+
export type BrowserSafetyLevel = "readOnly" | "write" | "destructiveWithApproval";
|
|
74
|
+
export interface BrowserSessionEntry {
|
|
75
|
+
readonly sessionId: string;
|
|
76
|
+
/**
|
|
77
|
+
* The run id every R4 edge this session witnesses is stamped with.
|
|
78
|
+
*
|
|
79
|
+
* One per session, not one per call: an edge's `observedByRun` answers
|
|
80
|
+
* "which run saw this", and a run that changed identity between a click and
|
|
81
|
+
* the request it caused would make that answer meaningless.
|
|
82
|
+
*/
|
|
83
|
+
readonly runId: string;
|
|
84
|
+
readonly page: BrowserPageSession;
|
|
85
|
+
/** The profile this session was opened under, or null when none was declared. */
|
|
86
|
+
readonly profile: {
|
|
87
|
+
readonly name: string;
|
|
88
|
+
readonly safetyLevel: BrowserSafetyLevel;
|
|
89
|
+
} | null;
|
|
90
|
+
/**
|
|
91
|
+
* The origin `browser_start_session` was consented for.
|
|
92
|
+
*
|
|
93
|
+
* Recorded at open time rather than read from the page later: the consent
|
|
94
|
+
* ruling binds the grant to the origin the developer approved, and a page
|
|
95
|
+
* that has since navigated is exactly the case where re-deriving it would
|
|
96
|
+
* launder a cross-origin move into an approved one.
|
|
97
|
+
*/
|
|
98
|
+
readonly consentedOrigin: string;
|
|
99
|
+
readonly openedAt: number;
|
|
100
|
+
readonly lastUsedAt: number;
|
|
101
|
+
}
|
|
102
|
+
export interface ReapedSession {
|
|
103
|
+
readonly sessionId: string;
|
|
104
|
+
readonly reason: ReapReason;
|
|
105
|
+
readonly observation: BrowserObservation;
|
|
106
|
+
readonly at: number;
|
|
107
|
+
}
|
|
108
|
+
export type OpenResult = {
|
|
109
|
+
readonly opened: true;
|
|
110
|
+
readonly entry: BrowserSessionEntry;
|
|
111
|
+
} | {
|
|
112
|
+
readonly opened: false;
|
|
113
|
+
readonly kind: "atCapacity";
|
|
114
|
+
readonly reason: string;
|
|
115
|
+
} | ({
|
|
116
|
+
readonly opened: false;
|
|
117
|
+
readonly kind: "chromiumNotInstalled";
|
|
118
|
+
} & ChromiumRefusal);
|
|
119
|
+
export type UseResult = {
|
|
120
|
+
readonly ok: true;
|
|
121
|
+
readonly entry: BrowserSessionEntry;
|
|
122
|
+
} | {
|
|
123
|
+
readonly ok: false;
|
|
124
|
+
readonly kind: "unknown";
|
|
125
|
+
readonly reason: string;
|
|
126
|
+
} | {
|
|
127
|
+
readonly ok: false;
|
|
128
|
+
readonly kind: "crashed" | "reaped";
|
|
129
|
+
readonly reason: string;
|
|
130
|
+
readonly reaped: ReapedSession;
|
|
131
|
+
};
|
|
132
|
+
export interface BrowserOpenOptions extends BrowserLaunchOptions {
|
|
133
|
+
/** The environment profile this session runs under. Read, never invented — see `BrowserSafetyLevel`. */
|
|
134
|
+
readonly profile?: {
|
|
135
|
+
readonly name: string;
|
|
136
|
+
readonly safetyLevel: BrowserSafetyLevel;
|
|
137
|
+
} | null;
|
|
138
|
+
}
|
|
139
|
+
export interface BrowserSessionRegistryOptions {
|
|
140
|
+
readonly now?: () => number;
|
|
141
|
+
readonly maxSessions?: number;
|
|
142
|
+
readonly idleTimeoutMs?: number;
|
|
143
|
+
/**
|
|
144
|
+
* Whether to run the background idle sweep.
|
|
145
|
+
*
|
|
146
|
+
* True in production: a session that goes idle because the agent wandered
|
|
147
|
+
* off is precisely the session that will never trigger a lazy sweep, so the
|
|
148
|
+
* timeout cannot be enforced only on the next call. The timer is `unref`'d,
|
|
149
|
+
* so it never holds the process open by itself.
|
|
150
|
+
*
|
|
151
|
+
* False in tests, which drive `sweepIdle()` against an injected clock —
|
|
152
|
+
* a real timer would make the idle assertions take real minutes.
|
|
153
|
+
*/
|
|
154
|
+
readonly startSweeper?: boolean;
|
|
155
|
+
}
|
|
156
|
+
export interface BrowserSessionRegistry {
|
|
157
|
+
readonly idleTimeoutMs: number;
|
|
158
|
+
readonly maxSessions: number;
|
|
159
|
+
open(driver: BrowserDriver, options: BrowserOpenOptions): Promise<OpenResult>;
|
|
160
|
+
/**
|
|
161
|
+
* Look a session up for use, touching its idle clock. Detects a crash
|
|
162
|
+
* before handing anything back.
|
|
163
|
+
*
|
|
164
|
+
* Asynchronous because the crash path is not a lookup — it is a teardown.
|
|
165
|
+
* A synchronous `use` would have to either drop the dead page's final
|
|
166
|
+
* evidence or pretend to have collected it, and the first draft of this
|
|
167
|
+
* file did the second: it returned a record it then filled in from a
|
|
168
|
+
* floating promise, so the flush landed after the caller had already read
|
|
169
|
+
* the record. Awaiting the reap here is what makes "a crash flushes what
|
|
170
|
+
* preceded it" true rather than nearly true.
|
|
171
|
+
*/
|
|
172
|
+
use(sessionId: string): Promise<UseResult>;
|
|
173
|
+
close(sessionId: string): Promise<BrowserObservation>;
|
|
174
|
+
sweepIdle(): Promise<readonly ReapedSession[]>;
|
|
175
|
+
reapAll(reason: ReapReason): Promise<readonly ReapedSession[]>;
|
|
176
|
+
reaped(sessionId: string): ReapedSession | undefined;
|
|
177
|
+
openCount(): number;
|
|
178
|
+
/** Stop the background sweeper. Called when the connection's `Session` is disposed. */
|
|
179
|
+
stop(): void;
|
|
180
|
+
}
|
|
181
|
+
export declare function createBrowserSessionRegistry(options?: BrowserSessionRegistryOptions): BrowserSessionRegistry;
|
|
182
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/browser/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EAChB,MAAM,aAAa,CAAC;AAGrB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB,QAAgB,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAItC,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,kBAAkB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEnF;;;;;;;;;GASG;AACH,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,OAAO,GAAG,yBAAyB,CAAC;AAElF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7F;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE,GAC9D;IAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChF,CAAC;IAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAA;CAAE,GAAG,eAAe,CAAC,CAAC;AAE1F,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC;AAEzH,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,wGAAwG;IACxG,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAA;KAAE,GAAG,IAAI,CAAC;CAC/F;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC9E;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3C,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtD,SAAS,IAAI,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAAC;IAC/D,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IACrD,SAAS,IAAI,MAAM,CAAC;IACpB,uFAAuF;IACvF,IAAI,IAAI,IAAI,CAAC;CACd;AAsBD,wBAAgB,4BAA4B,CAAC,OAAO,GAAE,6BAAkC,GAAG,sBAAsB,CA6HhH"}
|