@hraness/direct 0.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +436 -0
  3. package/dist/core/index.js +162 -0
  4. package/dist/index-1csg00w4.js +1167 -0
  5. package/dist/index-6mdfd2ey.js +464 -0
  6. package/dist/index-7n1h75n6.js +616 -0
  7. package/dist/index.js +232 -0
  8. package/dist/react.js +32 -0
  9. package/dist/testing/index.js +1069 -0
  10. package/dist/tooling/bombadil.js +2117 -0
  11. package/dist/tooling/browser-verification-entry.js +1499 -0
  12. package/dist/tooling/bundle-boundary.js +119 -0
  13. package/dist/web.js +605 -0
  14. package/package.json +179 -0
  15. package/skills/direct/AGENTS.md +13 -0
  16. package/skills/direct/SKILL.md +49 -0
  17. package/skills/direct/agents/openai.yaml +4 -0
  18. package/skills/direct/references/adoption.md +131 -0
  19. package/skills/direct/references/install.md +91 -0
  20. package/skills/direct/references/verification.md +247 -0
  21. package/src/core/coverage.ts +336 -0
  22. package/src/core/definition.ts +378 -0
  23. package/src/core/effects.ts +88 -0
  24. package/src/core/fixture.ts +185 -0
  25. package/src/core/ids.ts +77 -0
  26. package/src/core/index.ts +13 -0
  27. package/src/core/json-value.ts +7 -0
  28. package/src/core/json.ts +593 -0
  29. package/src/core/query.ts +230 -0
  30. package/src/core/reason.ts +16 -0
  31. package/src/core/resource.ts +10 -0
  32. package/src/core/result.ts +19 -0
  33. package/src/core/runtime.ts +229 -0
  34. package/src/core/scenario.ts +149 -0
  35. package/src/core/store.ts +784 -0
  36. package/src/index.ts +51 -0
  37. package/src/react.ts +54 -0
  38. package/src/testing/activity.ts +228 -0
  39. package/src/testing/coverage-binding.ts +99 -0
  40. package/src/testing/evidence.ts +59 -0
  41. package/src/testing/index.ts +22 -0
  42. package/src/testing/manifest.ts +559 -0
  43. package/src/testing/probe.ts +446 -0
  44. package/src/testing/scripted-transport.ts +775 -0
  45. package/src/testing/session.ts +525 -0
  46. package/src/tooling/bombadil-campaign.ts +288 -0
  47. package/src/tooling/bombadil-internal.d.ts +46 -0
  48. package/src/tooling/bombadil-runner.ts +1424 -0
  49. package/src/tooling/bombadil.ts +27 -0
  50. package/src/tooling/browser-verification-entry.ts +32 -0
  51. package/src/tooling/browser-verification.ts +916 -0
  52. package/src/tooling/bundle-boundary.ts +159 -0
  53. package/src/web/browser-bridge.ts +296 -0
  54. package/src/web/browser.ts +277 -0
  55. package/src/web/fetch-firewall.ts +251 -0
  56. package/src/web.ts +27 -0
package/dist/web.js ADDED
@@ -0,0 +1,605 @@
1
+ import {
2
+ parseDirectProbeSnapshot,
3
+ parseDirectSessionManifest
4
+ } from "./index-7n1h75n6.js";
5
+ import {
6
+ err,
7
+ ok,
8
+ renderUnknownReason
9
+ } from "./index-1csg00w4.js";
10
+
11
+ // src/web/browser-bridge.ts
12
+ var DIRECT_BROWSER_BRIDGE_SCHEMA = "direct.browser-bridge/v2";
13
+ var BRIDGE_KEYS = ["__direct"];
14
+ var activeBridgeInstallation = null;
15
+ function bridgeError(code, message) {
16
+ return Object.freeze({ code, message });
17
+ }
18
+ function containPromiseLike(value) {
19
+ if ((typeof value !== "object" || value === null) && typeof value !== "function")
20
+ return false;
21
+ let then;
22
+ try {
23
+ then = Reflect.get(value, "then");
24
+ } catch {
25
+ return false;
26
+ }
27
+ if (typeof then !== "function")
28
+ return false;
29
+ try {
30
+ Promise.resolve(value).catch(() => {
31
+ return;
32
+ });
33
+ } catch {}
34
+ return true;
35
+ }
36
+ function requireSynchronousResetResult(value) {
37
+ containPromiseLike(value);
38
+ if (value !== undefined) {
39
+ throw new Error("Direct reset must complete synchronously and return undefined");
40
+ }
41
+ return;
42
+ }
43
+ function defaultReset() {
44
+ const target = globalThis;
45
+ return requireSynchronousResetResult(target.location?.reload?.());
46
+ }
47
+ function restoreDescriptor(target, key, descriptor) {
48
+ if (descriptor === undefined) {
49
+ Reflect.deleteProperty(target, key);
50
+ } else {
51
+ Object.defineProperty(target, key, descriptor);
52
+ }
53
+ }
54
+ function restoreInstalledValue(target, key, installedValue, previous) {
55
+ try {
56
+ const descriptor = Object.getOwnPropertyDescriptor(target, key);
57
+ if (descriptor?.value === installedValue)
58
+ restoreDescriptor(target, key, previous);
59
+ } catch {}
60
+ }
61
+ function prepareDirectBrowserBridgeInstallation(options) {
62
+ let manifestInput;
63
+ try {
64
+ manifestInput = options.manifest;
65
+ } catch (reason) {
66
+ return err(bridgeError("invalid-manifest", renderUnknownReason(reason, "Failed to read the Direct session manifest")));
67
+ }
68
+ const parsedManifest = parseDirectSessionManifest(manifestInput);
69
+ if (!parsedManifest.ok) {
70
+ return err(bridgeError("invalid-manifest", parsedManifest.error.message));
71
+ }
72
+ const manifest = parsedManifest.value;
73
+ let target;
74
+ let reset;
75
+ let probe;
76
+ try {
77
+ target = options.target ?? globalThis;
78
+ reset = options.reset ?? defaultReset;
79
+ probe = options.probe;
80
+ } catch (reason) {
81
+ return err(bridgeError("install-failed", renderUnknownReason(reason, "Failed to read Direct browser bridge options")));
82
+ }
83
+ const previousInstallation = activeBridgeInstallation;
84
+ const rollbackDescriptors = new Map;
85
+ const restore = new Map;
86
+ try {
87
+ for (const key of BRIDGE_KEYS) {
88
+ const descriptor = Object.getOwnPropertyDescriptor(target, key);
89
+ rollbackDescriptors.set(key, descriptor);
90
+ const previousOwnsValue = previousInstallation?.target === target && descriptor?.value === previousInstallation.installed.get(key);
91
+ restore.set(key, previousOwnsValue ? previousInstallation.restore.get(key) : descriptor);
92
+ }
93
+ } catch (reason) {
94
+ return err(bridgeError("install-failed", renderUnknownReason(reason, "Failed to inspect the Direct browser bridge target")));
95
+ }
96
+ const readSnapshot = () => {
97
+ try {
98
+ const snapshot = probe.snapshot();
99
+ if (containPromiseLike(snapshot)) {
100
+ throw new Error("Direct probe snapshots must complete synchronously");
101
+ }
102
+ if ((typeof snapshot !== "object" || snapshot === null) && typeof snapshot !== "function") {
103
+ throw new Error("Direct probe returned an invalid result");
104
+ }
105
+ const succeeded = Reflect.get(snapshot, "ok");
106
+ if (succeeded !== true) {
107
+ if (succeeded === false)
108
+ throw new Error(renderUnknownReason(Reflect.get(snapshot, "error")));
109
+ throw new Error("Direct probe returned an invalid result");
110
+ }
111
+ const parsed = parseDirectProbeSnapshot(Reflect.get(snapshot, "value"));
112
+ if (!parsed.ok)
113
+ throw new Error(parsed.error.message);
114
+ if (parsed.value.activationHash !== manifest.active.activationHash) {
115
+ throw new Error("Direct probe activation hash does not match the installed session manifest");
116
+ }
117
+ return parsed.value;
118
+ } catch (reason) {
119
+ throw new Error(`Direct probe failed: ${renderUnknownReason(reason)}`);
120
+ }
121
+ };
122
+ const runReset = () => {
123
+ try {
124
+ const returned = reset();
125
+ return requireSynchronousResetResult(returned);
126
+ } catch (reason) {
127
+ throw new Error(`Direct reset failed: ${renderUnknownReason(reason)}`);
128
+ }
129
+ };
130
+ const bridge = Object.freeze({
131
+ schema: DIRECT_BROWSER_BRIDGE_SCHEMA,
132
+ manifest,
133
+ snapshot: readSnapshot,
134
+ reset: runReset
135
+ });
136
+ const installed = new Map([["__direct", bridge]]);
137
+ try {
138
+ for (const [key, value] of installed) {
139
+ Object.defineProperty(target, key, {
140
+ configurable: true,
141
+ enumerable: false,
142
+ writable: true,
143
+ value
144
+ });
145
+ }
146
+ } catch (reason) {
147
+ for (const key of BRIDGE_KEYS) {
148
+ restoreInstalledValue(target, key, installed.get(key), rollbackDescriptors.get(key));
149
+ }
150
+ return err(bridgeError("install-failed", renderUnknownReason(reason, "Direct browser bridge installation failed")));
151
+ }
152
+ let state = "prepared";
153
+ const rollback = () => {
154
+ if (state !== "prepared")
155
+ return;
156
+ state = "closed";
157
+ for (const key of BRIDGE_KEYS) {
158
+ restoreInstalledValue(target, key, installed.get(key), rollbackDescriptors.get(key));
159
+ }
160
+ return;
161
+ };
162
+ const deactivate = () => {
163
+ if (state !== "committed")
164
+ return;
165
+ state = "closed";
166
+ if (activeBridgeInstallation === installation)
167
+ activeBridgeInstallation = null;
168
+ return;
169
+ };
170
+ const uninstall = () => {
171
+ if (state === "prepared")
172
+ return rollback();
173
+ if (state !== "committed")
174
+ return;
175
+ state = "closed";
176
+ for (const key of BRIDGE_KEYS) {
177
+ restoreInstalledValue(target, key, installed.get(key), restore.get(key));
178
+ }
179
+ if (activeBridgeInstallation === installation)
180
+ activeBridgeInstallation = null;
181
+ return;
182
+ };
183
+ const installation = Object.freeze({
184
+ target,
185
+ installed,
186
+ restore,
187
+ deactivate,
188
+ uninstall
189
+ });
190
+ const commit = () => {
191
+ if (state !== "prepared")
192
+ return;
193
+ state = "committed";
194
+ if (previousInstallation !== null) {
195
+ if (previousInstallation.target === target)
196
+ previousInstallation.deactivate();
197
+ else
198
+ previousInstallation.uninstall();
199
+ }
200
+ activeBridgeInstallation = installation;
201
+ return;
202
+ };
203
+ return ok(Object.freeze({
204
+ commit,
205
+ rollback,
206
+ uninstall
207
+ }));
208
+ }
209
+ function installDirectBrowserBridge(options) {
210
+ const prepared = prepareDirectBrowserBridgeInstallation(options);
211
+ if (!prepared.ok)
212
+ return prepared;
213
+ prepared.value.commit();
214
+ return ok(prepared.value.uninstall);
215
+ }
216
+
217
+ // src/web/fetch-firewall.ts
218
+ var activeFirewallInstallation = null;
219
+ function containPromiseLike2(value) {
220
+ if ((typeof value !== "object" || value === null) && typeof value !== "function")
221
+ return false;
222
+ let then;
223
+ try {
224
+ then = Reflect.get(value, "then");
225
+ } catch {
226
+ return false;
227
+ }
228
+ if (typeof then !== "function")
229
+ return false;
230
+ try {
231
+ Promise.resolve(value).catch(() => {
232
+ return;
233
+ });
234
+ } catch {}
235
+ return true;
236
+ }
237
+ function requestUrl(input) {
238
+ try {
239
+ if (typeof Request !== "undefined" && input instanceof Request)
240
+ return new URL(input.url);
241
+ const browserGlobal = globalThis;
242
+ const locationOrigin = browserGlobal.location?.origin;
243
+ const base = locationOrigin === undefined || locationOrigin === "null" ? "http://direct.invalid" : locationOrigin;
244
+ return new URL(String(input), base);
245
+ } catch {
246
+ return null;
247
+ }
248
+ }
249
+ function blockedResponse() {
250
+ return new Response(JSON.stringify({ error: "Direct blocked an unmapped network request." }), { status: 501, headers: { "content-type": "application/json" } });
251
+ }
252
+ function beginBoundary(beginActivity, url) {
253
+ if (beginActivity === undefined) {
254
+ return { valid: true, release: () => {
255
+ return;
256
+ } };
257
+ }
258
+ let candidate;
259
+ try {
260
+ candidate = beginActivity(url);
261
+ } catch {
262
+ return { valid: false, release: () => {
263
+ return;
264
+ } };
265
+ }
266
+ if (containPromiseLike2(candidate) || typeof candidate !== "function") {
267
+ return { valid: false, release: () => {
268
+ return;
269
+ } };
270
+ }
271
+ let active = true;
272
+ return {
273
+ valid: true,
274
+ release: () => {
275
+ if (!active)
276
+ return;
277
+ active = false;
278
+ try {
279
+ const returned = Reflect.apply(candidate, undefined, []);
280
+ containPromiseLike2(returned);
281
+ } catch {}
282
+ return;
283
+ }
284
+ };
285
+ }
286
+ function explicitlyAllowed(allow, url) {
287
+ if (allow === undefined || url === null)
288
+ return false;
289
+ try {
290
+ const returned = allow(url);
291
+ if (containPromiseLike2(returned))
292
+ return false;
293
+ return returned === true;
294
+ } catch {
295
+ return false;
296
+ }
297
+ }
298
+ function notifyBlocked(onBlocked, url) {
299
+ if (onBlocked === undefined)
300
+ return;
301
+ try {
302
+ const returned = onBlocked(url);
303
+ containPromiseLike2(returned);
304
+ } catch {}
305
+ }
306
+ function prepareDirectFetchFirewallInstallation(options = {}) {
307
+ const previousInstallation = activeFirewallInstallation;
308
+ const currentFetch = globalThis.fetch;
309
+ const previousOwnsCurrent = previousInstallation?.guardedFetch === currentFetch;
310
+ const restoreFetch = previousOwnsCurrent ? previousInstallation.restoreFetch : currentFetch;
311
+ const allow = options.allow;
312
+ const beginActivity = options.beginActivity;
313
+ const onBlocked = options.onBlocked;
314
+ const originalFetch = options.originalFetch ?? restoreFetch;
315
+ if (typeof originalFetch !== "function") {
316
+ throw new TypeError("Direct fetch firewall requires a callable fetch implementation");
317
+ }
318
+ const guardedCall = async (input, init) => {
319
+ const url = requestUrl(input);
320
+ const activity = beginBoundary(beginActivity, url);
321
+ try {
322
+ if (activity.valid && explicitlyAllowed(allow, url)) {
323
+ return await originalFetch(input, init);
324
+ }
325
+ notifyBlocked(onBlocked, url);
326
+ return blockedResponse();
327
+ } finally {
328
+ activity.release();
329
+ }
330
+ };
331
+ const previousPreconnect = Reflect.get(restoreFetch, "preconnect");
332
+ if (typeof previousPreconnect === "function") {
333
+ Object.defineProperty(guardedCall, "preconnect", {
334
+ configurable: true,
335
+ value: (...arguments_) => {
336
+ const url = requestUrl(arguments_[0]);
337
+ const activity = beginBoundary(beginActivity, url);
338
+ try {
339
+ if (activity.valid && explicitlyAllowed(allow, url)) {
340
+ const returned = Reflect.apply(previousPreconnect, restoreFetch, arguments_);
341
+ containPromiseLike2(returned);
342
+ } else {
343
+ notifyBlocked(onBlocked, url);
344
+ }
345
+ } finally {
346
+ activity.release();
347
+ }
348
+ return;
349
+ }
350
+ });
351
+ }
352
+ const guardedFetch = guardedCall;
353
+ try {
354
+ globalThis.fetch = guardedFetch;
355
+ if (globalThis.fetch !== guardedFetch) {
356
+ throw new TypeError("Direct fetch firewall could not replace global fetch");
357
+ }
358
+ } catch (reason) {
359
+ try {
360
+ if (globalThis.fetch === guardedFetch)
361
+ globalThis.fetch = currentFetch;
362
+ } catch {}
363
+ throw reason;
364
+ }
365
+ let state = "prepared";
366
+ const rollback = () => {
367
+ if (state !== "prepared")
368
+ return;
369
+ if (globalThis.fetch === guardedFetch)
370
+ globalThis.fetch = currentFetch;
371
+ state = "closed";
372
+ return;
373
+ };
374
+ const deactivate = () => {
375
+ if (state !== "committed")
376
+ return;
377
+ state = "closed";
378
+ if (activeFirewallInstallation === installation)
379
+ activeFirewallInstallation = null;
380
+ return;
381
+ };
382
+ const uninstall = () => {
383
+ if (state === "prepared")
384
+ return rollback();
385
+ if (state !== "committed")
386
+ return;
387
+ if (globalThis.fetch === guardedFetch)
388
+ globalThis.fetch = restoreFetch;
389
+ state = "closed";
390
+ if (activeFirewallInstallation === installation)
391
+ activeFirewallInstallation = null;
392
+ return;
393
+ };
394
+ const installation = {
395
+ guardedFetch,
396
+ restoreFetch,
397
+ deactivate,
398
+ uninstall
399
+ };
400
+ const commit = () => {
401
+ if (state !== "prepared")
402
+ return;
403
+ state = "committed";
404
+ if (previousInstallation !== null)
405
+ previousInstallation.deactivate();
406
+ activeFirewallInstallation = installation;
407
+ return;
408
+ };
409
+ return Object.freeze({
410
+ commit,
411
+ rollback,
412
+ uninstall
413
+ });
414
+ }
415
+ function installDirectFetchFirewall(options = {}) {
416
+ const prepared = prepareDirectFetchFirewallInstallation(options);
417
+ prepared.commit();
418
+ return prepared.uninstall;
419
+ }
420
+
421
+ // src/web/browser.ts
422
+ function freezeMessages(messages) {
423
+ return Object.freeze([...messages]);
424
+ }
425
+ function containPromiseLike3(value) {
426
+ if ((typeof value !== "object" || value === null) && typeof value !== "function")
427
+ return false;
428
+ let then;
429
+ try {
430
+ then = Reflect.get(value, "then");
431
+ } catch {
432
+ return false;
433
+ }
434
+ if (typeof then !== "function")
435
+ return false;
436
+ try {
437
+ Promise.resolve(value).catch(() => {
438
+ return;
439
+ });
440
+ } catch {}
441
+ return true;
442
+ }
443
+ function notifyActivityError(observer, error) {
444
+ if (observer === undefined)
445
+ return;
446
+ try {
447
+ const returned = observer(error);
448
+ containPromiseLike3(returned);
449
+ } catch {}
450
+ }
451
+ function runBrowserCleanup(bridge, firewall) {
452
+ const errors = [];
453
+ for (const [label, cleanup] of [
454
+ ["bridge", bridge],
455
+ ["firewall", firewall]
456
+ ]) {
457
+ if (cleanup === null)
458
+ continue;
459
+ try {
460
+ const returned = cleanup();
461
+ if (returned !== undefined) {
462
+ containPromiseLike3(returned);
463
+ errors.push(`Direct browser ${label} cleanup must return undefined`);
464
+ }
465
+ } catch (reason) {
466
+ errors.push(renderUnknownReason(reason, `Direct browser ${label} cleanup failed`));
467
+ }
468
+ }
469
+ return freezeMessages(errors);
470
+ }
471
+ function installDirectBrowser(options) {
472
+ let activity;
473
+ let manifest;
474
+ let onDispose;
475
+ let probe;
476
+ let reset;
477
+ let target;
478
+ let firewallOptions;
479
+ try {
480
+ const session = options.session;
481
+ activity = session.activity;
482
+ manifest = session.manifest;
483
+ onDispose = session.onDispose;
484
+ probe = session.probe;
485
+ reset = options.reset;
486
+ target = options.target;
487
+ firewallOptions = options.firewall ?? {};
488
+ } catch (reason) {
489
+ return err(Object.freeze({
490
+ code: "invalid-options",
491
+ message: renderUnknownReason(reason, "Direct browser options could not be inspected"),
492
+ bridgeError: null,
493
+ registrationError: null,
494
+ rollbackErrors: freezeMessages([])
495
+ }));
496
+ }
497
+ let preparedFirewall = null;
498
+ if (firewallOptions !== false) {
499
+ try {
500
+ const { onActivityError, ...lowLevelOptions } = firewallOptions;
501
+ preparedFirewall = prepareDirectFetchFirewallInstallation({
502
+ ...lowLevelOptions,
503
+ beginActivity: () => {
504
+ const started = activity.begin("browser-fetch");
505
+ if (!started.ok) {
506
+ notifyActivityError(onActivityError, started.error);
507
+ throw new Error(started.error.message, { cause: started.error });
508
+ }
509
+ return () => {
510
+ const released = started.value.release();
511
+ if (!released.ok)
512
+ notifyActivityError(onActivityError, released.error);
513
+ return;
514
+ };
515
+ }
516
+ });
517
+ } catch (reason) {
518
+ return err(Object.freeze({
519
+ code: "firewall-install-failed",
520
+ message: renderUnknownReason(reason, "Direct fetch firewall installation failed"),
521
+ bridgeError: null,
522
+ registrationError: null,
523
+ rollbackErrors: freezeMessages([])
524
+ }));
525
+ }
526
+ }
527
+ const preparedBridgeResult = prepareDirectBrowserBridgeInstallation({
528
+ probe,
529
+ manifest,
530
+ ...reset === undefined ? {} : { reset },
531
+ ...target === undefined ? {} : { target }
532
+ });
533
+ if (!preparedBridgeResult.ok) {
534
+ const rollbackErrors = runBrowserCleanup(null, preparedFirewall?.rollback ?? null);
535
+ return err(Object.freeze({
536
+ code: "bridge-install-failed",
537
+ message: preparedBridgeResult.error.message,
538
+ bridgeError: preparedBridgeResult.error,
539
+ registrationError: null,
540
+ rollbackErrors
541
+ }));
542
+ }
543
+ const preparedBridge = preparedBridgeResult.value;
544
+ let disposed = false;
545
+ let committed = false;
546
+ let disposalErrors = freezeMessages([]);
547
+ const dispose = () => {
548
+ if (disposed)
549
+ return;
550
+ disposed = true;
551
+ disposalErrors = committed ? runBrowserCleanup(preparedBridge.uninstall, preparedFirewall?.uninstall ?? null) : runBrowserCleanup(preparedBridge.rollback, preparedFirewall?.rollback ?? null);
552
+ return;
553
+ };
554
+ const installation = Object.freeze({
555
+ dispose,
556
+ isDisposed: () => disposed,
557
+ disposalErrors: () => disposalErrors
558
+ });
559
+ try {
560
+ const registered = onDispose(dispose);
561
+ if (!registered.ok) {
562
+ dispose();
563
+ return err(Object.freeze({
564
+ code: "session-registration-failed",
565
+ message: registered.error.message,
566
+ bridgeError: null,
567
+ registrationError: registered.error,
568
+ rollbackErrors: disposalErrors
569
+ }));
570
+ }
571
+ } catch (reason) {
572
+ dispose();
573
+ return err(Object.freeze({
574
+ code: "session-registration-threw",
575
+ message: renderUnknownReason(reason, "Direct session cleanup registration failed"),
576
+ bridgeError: null,
577
+ registrationError: null,
578
+ rollbackErrors: disposalErrors
579
+ }));
580
+ }
581
+ if (disposed) {
582
+ return err(Object.freeze({
583
+ code: "session-registration-threw",
584
+ message: "Direct session disposed browser ownership during cleanup registration",
585
+ bridgeError: null,
586
+ registrationError: null,
587
+ rollbackErrors: disposalErrors
588
+ }));
589
+ }
590
+ preparedFirewall?.commit();
591
+ preparedBridge.commit();
592
+ committed = true;
593
+ return ok(installation);
594
+ }
595
+
596
+ // src/web.ts
597
+ var DIRECT_BROWSER_BRIDGE_SCHEMA2 = DIRECT_BROWSER_BRIDGE_SCHEMA;
598
+ var installDirectBrowserBridge2 = (options) => installDirectBrowserBridge(options);
599
+ var installDirectFetchFirewall2 = (options) => installDirectFetchFirewall(options);
600
+ export {
601
+ installDirectFetchFirewall2 as installDirectFetchFirewall,
602
+ installDirectBrowserBridge2 as installDirectBrowserBridge,
603
+ installDirectBrowser,
604
+ DIRECT_BROWSER_BRIDGE_SCHEMA2 as DIRECT_BROWSER_BRIDGE_SCHEMA
605
+ };