@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.
Files changed (160) hide show
  1. package/dist/bin/descry-mcp.js +6 -1
  2. package/dist/bin/descry-mcp.js.map +1 -1
  3. package/dist/browser/driver.d.ts +236 -0
  4. package/dist/browser/driver.d.ts.map +1 -0
  5. package/dist/browser/driver.js +70 -0
  6. package/dist/browser/driver.js.map +1 -0
  7. package/dist/browser/evidence.d.ts +47 -0
  8. package/dist/browser/evidence.d.ts.map +1 -0
  9. package/dist/browser/evidence.js +55 -0
  10. package/dist/browser/evidence.js.map +1 -0
  11. package/dist/browser/fake-driver.d.ts +58 -0
  12. package/dist/browser/fake-driver.d.ts.map +1 -0
  13. package/dist/browser/fake-driver.js +161 -0
  14. package/dist/browser/fake-driver.js.map +1 -0
  15. package/dist/browser/graph-write.d.ts +86 -0
  16. package/dist/browser/graph-write.d.ts.map +1 -0
  17. package/dist/browser/graph-write.js +135 -0
  18. package/dist/browser/graph-write.js.map +1 -0
  19. package/dist/browser/playwright-driver.d.ts +65 -0
  20. package/dist/browser/playwright-driver.d.ts.map +1 -0
  21. package/dist/browser/playwright-driver.js +359 -0
  22. package/dist/browser/playwright-driver.js.map +1 -0
  23. package/dist/browser/provider.d.ts +49 -0
  24. package/dist/browser/provider.d.ts.map +1 -0
  25. package/dist/browser/provider.js +28 -0
  26. package/dist/browser/provider.js.map +1 -0
  27. package/dist/browser/registry.d.ts +182 -0
  28. package/dist/browser/registry.d.ts.map +1 -0
  29. package/dist/browser/registry.js +215 -0
  30. package/dist/browser/registry.js.map +1 -0
  31. package/dist/browser/scenario-resolve.d.ts +62 -0
  32. package/dist/browser/scenario-resolve.d.ts.map +1 -0
  33. package/dist/browser/scenario-resolve.js +127 -0
  34. package/dist/browser/scenario-resolve.js.map +1 -0
  35. package/dist/browser/scenario-runner.d.ts +113 -0
  36. package/dist/browser/scenario-runner.d.ts.map +1 -0
  37. package/dist/browser/scenario-runner.js +315 -0
  38. package/dist/browser/scenario-runner.js.map +1 -0
  39. package/dist/browser/stack-parser.d.ts +43 -0
  40. package/dist/browser/stack-parser.d.ts.map +1 -0
  41. package/dist/browser/stack-parser.js +112 -0
  42. package/dist/browser/stack-parser.js.map +1 -0
  43. package/dist/browser/tool-support.d.ts +113 -0
  44. package/dist/browser/tool-support.d.ts.map +1 -0
  45. package/dist/browser/tool-support.js +181 -0
  46. package/dist/browser/tool-support.js.map +1 -0
  47. package/dist/index.d.ts +11 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +10 -0
  50. package/dist/index.js.map +1 -1
  51. package/dist/render.d.ts +112 -10
  52. package/dist/render.d.ts.map +1 -1
  53. package/dist/render.js +79 -13
  54. package/dist/render.js.map +1 -1
  55. package/dist/scenarios/index.d.ts +4 -0
  56. package/dist/scenarios/index.d.ts.map +1 -0
  57. package/dist/scenarios/index.js +4 -0
  58. package/dist/scenarios/index.js.map +1 -0
  59. package/dist/scenarios/parse.d.ts +32 -0
  60. package/dist/scenarios/parse.d.ts.map +1 -0
  61. package/dist/scenarios/parse.js +199 -0
  62. package/dist/scenarios/parse.js.map +1 -0
  63. package/dist/scenarios/scenario.d.ts +115 -0
  64. package/dist/scenarios/scenario.d.ts.map +1 -0
  65. package/dist/scenarios/scenario.js +41 -0
  66. package/dist/scenarios/scenario.js.map +1 -0
  67. package/dist/scenarios/storage.d.ts +51 -0
  68. package/dist/scenarios/storage.d.ts.map +1 -0
  69. package/dist/scenarios/storage.js +93 -0
  70. package/dist/scenarios/storage.js.map +1 -0
  71. package/dist/server.d.ts.map +1 -1
  72. package/dist/server.js +6 -3
  73. package/dist/server.js.map +1 -1
  74. package/dist/session.d.ts +68 -0
  75. package/dist/session.d.ts.map +1 -1
  76. package/dist/session.js +89 -0
  77. package/dist/session.js.map +1 -1
  78. package/dist/tools/analyze.d.ts +41 -1
  79. package/dist/tools/analyze.d.ts.map +1 -1
  80. package/dist/tools/analyze.js +81 -8
  81. package/dist/tools/analyze.js.map +1 -1
  82. package/dist/tools/browser-click.d.ts +36 -0
  83. package/dist/tools/browser-click.d.ts.map +1 -0
  84. package/dist/tools/browser-click.js +117 -0
  85. package/dist/tools/browser-click.js.map +1 -0
  86. package/dist/tools/browser-close-session.d.ts +24 -0
  87. package/dist/tools/browser-close-session.d.ts.map +1 -0
  88. package/dist/tools/browser-close-session.js +63 -0
  89. package/dist/tools/browser-close-session.js.map +1 -0
  90. package/dist/tools/browser-fill.d.ts +49 -0
  91. package/dist/tools/browser-fill.d.ts.map +1 -0
  92. package/dist/tools/browser-fill.js +138 -0
  93. package/dist/tools/browser-fill.js.map +1 -0
  94. package/dist/tools/browser-navigate.d.ts +32 -0
  95. package/dist/tools/browser-navigate.d.ts.map +1 -0
  96. package/dist/tools/browser-navigate.js +103 -0
  97. package/dist/tools/browser-navigate.js.map +1 -0
  98. package/dist/tools/browser-run-scenario.d.ts +54 -0
  99. package/dist/tools/browser-run-scenario.d.ts.map +1 -0
  100. package/dist/tools/browser-run-scenario.js +228 -0
  101. package/dist/tools/browser-run-scenario.js.map +1 -0
  102. package/dist/tools/browser-save-scenario.d.ts +44 -0
  103. package/dist/tools/browser-save-scenario.d.ts.map +1 -0
  104. package/dist/tools/browser-save-scenario.js +298 -0
  105. package/dist/tools/browser-save-scenario.js.map +1 -0
  106. package/dist/tools/browser-snapshot.d.ts +60 -0
  107. package/dist/tools/browser-snapshot.d.ts.map +1 -0
  108. package/dist/tools/browser-snapshot.js +139 -0
  109. package/dist/tools/browser-snapshot.js.map +1 -0
  110. package/dist/tools/browser-start-session.d.ts +43 -0
  111. package/dist/tools/browser-start-session.d.ts.map +1 -0
  112. package/dist/tools/browser-start-session.js +272 -0
  113. package/dist/tools/browser-start-session.js.map +1 -0
  114. package/dist/tools/browser-type.d.ts +48 -0
  115. package/dist/tools/browser-type.d.ts.map +1 -0
  116. package/dist/tools/browser-type.js +136 -0
  117. package/dist/tools/browser-type.js.map +1 -0
  118. package/dist/tools/contracts.d.ts +15 -0
  119. package/dist/tools/contracts.d.ts.map +1 -1
  120. package/dist/tools/contracts.js +14 -3
  121. package/dist/tools/contracts.js.map +1 -1
  122. package/dist/tools/git-diff.d.ts.map +1 -1
  123. package/dist/tools/git-diff.js +85 -6
  124. package/dist/tools/git-diff.js.map +1 -1
  125. package/dist/tools/impact.d.ts +9 -0
  126. package/dist/tools/impact.d.ts.map +1 -1
  127. package/dist/tools/impact.js +3 -3
  128. package/dist/tools/impact.js.map +1 -1
  129. package/dist/tools/index.d.ts +9 -0
  130. package/dist/tools/index.d.ts.map +1 -1
  131. package/dist/tools/index.js +27 -0
  132. package/dist/tools/index.js.map +1 -1
  133. package/dist/tools/kit.d.ts +10 -1
  134. package/dist/tools/kit.d.ts.map +1 -1
  135. package/dist/tools/kit.js +2 -0
  136. package/dist/tools/kit.js.map +1 -1
  137. package/dist/tools/observe-runtime.d.ts +113 -19
  138. package/dist/tools/observe-runtime.d.ts.map +1 -1
  139. package/dist/tools/observe-runtime.js +324 -53
  140. package/dist/tools/observe-runtime.js.map +1 -1
  141. package/dist/tools/observe-tests.d.ts +125 -0
  142. package/dist/tools/observe-tests.d.ts.map +1 -0
  143. package/dist/tools/observe-tests.js +313 -0
  144. package/dist/tools/observe-tests.js.map +1 -0
  145. package/dist/tools/pr-analysis.d.ts +11 -0
  146. package/dist/tools/pr-analysis.d.ts.map +1 -1
  147. package/dist/tools/pr-analysis.js +3 -3
  148. package/dist/tools/pr-analysis.js.map +1 -1
  149. package/dist/tools/pre-push.d.ts +77 -0
  150. package/dist/tools/pre-push.d.ts.map +1 -0
  151. package/dist/tools/pre-push.js +250 -0
  152. package/dist/tools/pre-push.js.map +1 -0
  153. package/dist/tools/questions.d.ts.map +1 -1
  154. package/dist/tools/questions.js +41 -16
  155. package/dist/tools/questions.js.map +1 -1
  156. package/dist/tools/verification-status.d.ts +22 -0
  157. package/dist/tools/verification-status.d.ts.map +1 -1
  158. package/dist/tools/verification-status.js +51 -5
  159. package/dist/tools/verification-status.js.map +1 -1
  160. package/package.json +14 -13
@@ -65,7 +65,12 @@ async function main() {
65
65
  finally {
66
66
  // The SQLite handle and anything else with a lifetime. Held open past the
67
67
  // end of stdin, a WAL journal outlives the process that owned it.
68
- session.close();
68
+ //
69
+ // `dispose`, not `close`, because end-of-stdin is how an MCP host says
70
+ // "disconnect" — and §4 requires that signal to reap every browser this
71
+ // connection owns. A leaked SQLite handle costs a file descriptor; a
72
+ // leaked Chromium keeps running on the developer's machine.
73
+ await session.dispose();
69
74
  }
70
75
  }
71
76
  main().then((code) => {
@@ -1 +1 @@
1
- {"version":3,"file":"descry-mcp.js","sourceRoot":"","sources":["../../src/bin/descry-mcp.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;;;;;;;;;GAUG;AACH,MAAM,OAAO,GAAW,CAAC,GAAW,EAAE;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAA0B,CAAC;QAC1F,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,+DAA+D;QAC/D,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC,CAAC,EAAE,CAAC;AAEL,MAAM,KAAK,GAAG;;;;;;CAMb,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAE9E,IAAI,CAAC;QACH,MAAM,UAAU,CACd,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,EACxE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CACtD,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;YAAS,CAAC;QACT,0EAA0E;QAC1E,kEAAkE;QAClE,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,IAAI,CACT,CAAC,IAAI,EAAE,EAAE;IACP,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,eAAe,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CACzF,CAAC;IACF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CACF,CAAC"}
1
+ {"version":3,"file":"descry-mcp.js","sourceRoot":"","sources":["../../src/bin/descry-mcp.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;;;;;;;;;GAUG;AACH,MAAM,OAAO,GAAW,CAAC,GAAW,EAAE;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAA0B,CAAC;QAC1F,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,+DAA+D;QAC/D,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC,CAAC,EAAE,CAAC;AAEL,MAAM,KAAK,GAAG;;;;;;CAMb,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAE9E,IAAI,CAAC;QACH,MAAM,UAAU,CACd,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,EACxE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CACtD,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;YAAS,CAAC;QACT,0EAA0E;QAC1E,kEAAkE;QAClE,EAAE;QACF,uEAAuE;QACvE,wEAAwE;QACxE,qEAAqE;QACrE,4DAA4D;QAC5D,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,IAAI,CACT,CAAC,IAAI,EAAE,EAAE;IACP,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,eAAe,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CACzF,CAAC;IACF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CACF,CAAC"}
@@ -0,0 +1,236 @@
1
+ /**
2
+ * The browser port — what `@descryy/mcp` needs from a browser, stated as an
3
+ * interface this package owns.
4
+ *
5
+ * ## Why a port at all
6
+ *
7
+ * `@descryy/runtime-browser` is not on the registry yet
8
+ * (`mcp-browser-tools.md` §3.1), so a lane that imported it directly could
9
+ * not run today. That is the immediate reason and it is the weakest one.
10
+ * The lasting reason is that everything above this line — seven tools, the
11
+ * session registry, the scenario runner — otherwise becomes untestable
12
+ * without launching a real Chromium per assertion, and a suite that needs a
13
+ * browser to test its session bookkeeping is a suite people stop running.
14
+ *
15
+ * ## Derived, not invented
16
+ *
17
+ * Every member below exists because a real export in
18
+ * `descry-runtime/packages/browser/src/index.ts` provides it. The refusal
19
+ * shape is `launchBrowserSessionOrRefuse`'s verbatim; `isUsable()` is
20
+ * `BrowserSession`'s, including its reason for existing (a crashed page
21
+ * still reports `isClosed() === false`, so crash tracking cannot be derived
22
+ * from closure); the action verbs are `BrowserActionCollector`'s; the
23
+ * console and network observations are what the two collectors emit. The
24
+ * port narrows that surface — it does not add to it. Nothing here can be
25
+ * satisfied by the real package only by writing new runtime code, with one
26
+ * disclosed exception, `type()` below.
27
+ *
28
+ * ## What the port deliberately does not carry
29
+ *
30
+ * A verdict. There is no `severity`, no `isBug`, no `category` on any
31
+ * observation, because `DEC-381` rules that
32
+ * classification stays in the desktop pipeline. That is enforced structurally
33
+ * rather than by convention: a tool cannot report a triaged finding through
34
+ * a port that has nowhere to put one.
35
+ *
36
+ * Rule 1 holds here as everywhere — nothing in this file names a language, a
37
+ * framework, or a file extension.
38
+ */
39
+ import type { StackTrace } from "@descryy/runtime-contracts";
40
+ /** A page element as a snapshot presented it. `ref` is the handle an action takes. */
41
+ export interface SnapshotElement {
42
+ readonly ref: string;
43
+ readonly role: string;
44
+ readonly name: string;
45
+ /**
46
+ * How the driver will find this element again. Present so a reply can be
47
+ * read by a human, **not** so a caller can act on it: every verb takes a
48
+ * `ref`, never a selector, because a ref ties the action to a snapshot the
49
+ * agent actually saw and a selector does not.
50
+ */
51
+ readonly selector: string;
52
+ }
53
+ export interface PageSnapshot {
54
+ readonly url: string;
55
+ readonly title: string;
56
+ readonly elements: readonly SnapshotElement[];
57
+ /**
58
+ * How many elements the page had, before any budget applied.
59
+ *
60
+ * Always present, and always the uncapped figure. §5.2's requirement in one
61
+ * field: without it a caller cannot tell "there are no more elements" from
62
+ * "the rest did not fit", and those are different facts about their page.
63
+ * The driver never truncates — it returns what it saw and this equals
64
+ * `elements.length` here — but the field is on the port rather than
65
+ * invented by the tool, so the tool cannot lose track of the real count
66
+ * while paging.
67
+ */
68
+ readonly totalElements: number;
69
+ }
70
+ export type BrowserActionKind = "navigate" | "click" | "type" | "fill";
71
+ export interface ObservedAction {
72
+ readonly action: BrowserActionKind;
73
+ /** Null for `navigate`, which acts on the page rather than on an element. */
74
+ readonly ref: string | null;
75
+ /**
76
+ * How text reached the field — `"append"` for `type`, `"replace"` for
77
+ * `fill`, null for actions that enter no text.
78
+ *
79
+ * Carried because without it the two text verbs' evidence reads
80
+ * identically, and "the field now contains X" and "X was added to whatever
81
+ * the field already contained" are different facts about a run. The runtime
82
+ * collector's own `INPUT` payload carries the same field for the same
83
+ * reason.
84
+ */
85
+ readonly mode: "replace" | "append" | null;
86
+ readonly url: string;
87
+ readonly at: string;
88
+ }
89
+ export interface ObservedConsoleError {
90
+ readonly text: string;
91
+ /**
92
+ * Raw stack text as the page produced it, or null. **Not yet rewritten to
93
+ * real files and lines** — that is `rewriteScriptUrls`' job and it needs a
94
+ * source-root resolver the driver does not have. The port carries the raw
95
+ * text so the mapping happens once, above, where the repo root is known.
96
+ */
97
+ readonly stackText: string | null;
98
+ readonly at: string;
99
+ }
100
+ export interface ObservedRequest {
101
+ readonly method: string;
102
+ readonly url: string;
103
+ /** Null when the request produced no response at all, which is a different fact from a 500. */
104
+ readonly status: number | null;
105
+ /** The `fetch()` call site as raw text, when the initiator capture claimed one. Null is honest absence. */
106
+ readonly stackText: string | null;
107
+ /**
108
+ * The same call site, parsed into frames with real file paths.
109
+ *
110
+ * Null unless the caller named a stack-trace parser for the application
111
+ * being driven — this package cannot parse a stack itself without naming a
112
+ * language, which rule 1 forbids above the IR. **This is the field the R4
113
+ * edge write needs**: `confirmObservedFrontendCaller` takes a `StackTrace`,
114
+ * not text, and a run with no parser produces no arrow and says so.
115
+ */
116
+ readonly stackTrace: StackTrace | null;
117
+ readonly at: string;
118
+ }
119
+ /** A request that did not succeed. Mechanical, not a judgement: no response, or a 4xx/5xx status. */
120
+ export declare function isFailedRequest(request: ObservedRequest): boolean;
121
+ /** Everything witnessed since the last drain. Raw — see this file's header. */
122
+ export interface BrowserObservation {
123
+ readonly actions: readonly ObservedAction[];
124
+ readonly consoleErrors: readonly ObservedConsoleError[];
125
+ /**
126
+ * Every request the page issued, not only the ones that failed.
127
+ *
128
+ * A successful call is what proves *this frontend action reached this
129
+ * backend route* — the arrow the whole plan exists for — so filtering to
130
+ * failures here would throw away the evidence the R4 edge write runs on.
131
+ * The reply narrows to failures for readability; the correlation does not.
132
+ */
133
+ readonly requests: readonly ObservedRequest[];
134
+ }
135
+ export declare const EMPTY_OBSERVATION: BrowserObservation;
136
+ export interface BrowserLaunchOptions {
137
+ readonly targetUrl: string;
138
+ readonly headless?: boolean;
139
+ }
140
+ /**
141
+ * `launchBrowserSessionOrRefuse`'s refusal, unchanged.
142
+ *
143
+ * `remedy` is the exact command that fixes it, **supplied by the driver and
144
+ * never held as a constant in this package**. The real driver passes
145
+ * `CHROMIUM_INSTALL_REMEDY` through; a copy here would be a second source of
146
+ * truth for one string, and the copy is the one that goes stale.
147
+ */
148
+ export interface ChromiumRefusal {
149
+ readonly refusal: "chromiumNotInstalled";
150
+ readonly message: string;
151
+ readonly remedy: string;
152
+ readonly expectedExecutablePath: string;
153
+ }
154
+ export type BrowserLaunchResult = {
155
+ readonly launched: true;
156
+ readonly session: BrowserPageSession;
157
+ } | ({
158
+ readonly launched: false;
159
+ } & ChromiumRefusal);
160
+ /** The browser died. Distinct from a closed session: a crash invalidates the id rather than ending it cleanly. */
161
+ export declare class BrowserSessionCrashedError extends Error {
162
+ readonly sessionId: string;
163
+ constructor(sessionId: string);
164
+ }
165
+ /**
166
+ * The ref named no element in the current snapshot.
167
+ *
168
+ * Thrown for an invented ref **and** for a ref from a superseded snapshot,
169
+ * because those are the same mistake: acting on an element the agent has not
170
+ * seen. Falling back to the stale selector would let a click land on whatever
171
+ * now matches it on a page the caller has never inspected.
172
+ */
173
+ export declare class UnknownElementRefError extends Error {
174
+ constructor(ref: string);
175
+ }
176
+ export interface BrowserPageSession {
177
+ readonly sessionId: string;
178
+ /** When the page was actually created, ISO-8601. What evidence is ordered by. */
179
+ readonly startedAt: string;
180
+ /**
181
+ * False once the page has crashed or closed. Not derivable from closure —
182
+ * `runtime-browser` verified directly that a real crash still reports
183
+ * `isClosed() === false`, which is why this is a member rather than
184
+ * something a caller computes.
185
+ */
186
+ isUsable(): boolean;
187
+ currentUrl(): string;
188
+ navigate(url: string): Promise<void>;
189
+ snapshot(): Promise<PageSnapshot>;
190
+ click(ref: string): Promise<void>;
191
+ /**
192
+ * Type `text` as real keystrokes, appending to whatever the field holds.
193
+ *
194
+ * The append/replace difference against `fill` is the visible half. The
195
+ * half that decides which verb is correct for a page is that **this one
196
+ * fires key events and `fill` fires none**: a field that opens an
197
+ * autocomplete on keydown, validates per character, or debounces a search
198
+ * sees nothing at all from a `fill`. A caller reaching for `fill` on a
199
+ * search box gets a page that was never typed into — a wrong answer
200
+ * produced by entirely correct code — so both members exist and the tool
201
+ * prose has to state the real distinction, not the tidy one.
202
+ */
203
+ type(ref: string, text: string): Promise<void>;
204
+ /** Replace the element's value with `text`, setting it directly. Fires no key events. */
205
+ fill(ref: string, text: string): Promise<void>;
206
+ /**
207
+ * Everything witnessed since the last drain, removed from the session as it
208
+ * is returned.
209
+ *
210
+ * Drained rather than peeked, and that is a contract, not an implementation
211
+ * detail: §4 requires evidence to be flushed on four separate teardown
212
+ * paths, and a peeking read would make the flush re-report every
213
+ * observation already attached to an earlier reply.
214
+ */
215
+ drainEvidence(): Promise<BrowserObservation>;
216
+ /**
217
+ * Tear down and return whatever was still held.
218
+ *
219
+ * Idempotent, and returns the final flush rather than `void`. Evidence
220
+ * captured and then dropped is worse than evidence never captured, because
221
+ * nothing discloses it — so the last thing a session does is hand back what
222
+ * it was holding, on every path including a crash.
223
+ */
224
+ close(): Promise<BrowserObservation>;
225
+ }
226
+ export interface BrowserDriver {
227
+ /**
228
+ * Open a session at `targetUrl`, or refuse.
229
+ *
230
+ * A missing browser is a **returned value**, never a thrown error, so a
231
+ * tool mapping it onto the `refused` state cannot forget to catch it —
232
+ * `refused` is a fact about Descry, never about the user's code.
233
+ */
234
+ launch(options: BrowserLaunchOptions): Promise<BrowserLaunchResult>;
235
+ }
236
+ //# sourceMappingURL=driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/browser/driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The browser port — what `@descryy/mcp` needs from a browser, stated as an
3
+ * interface this package owns.
4
+ *
5
+ * ## Why a port at all
6
+ *
7
+ * `@descryy/runtime-browser` is not on the registry yet
8
+ * (`mcp-browser-tools.md` §3.1), so a lane that imported it directly could
9
+ * not run today. That is the immediate reason and it is the weakest one.
10
+ * The lasting reason is that everything above this line — seven tools, the
11
+ * session registry, the scenario runner — otherwise becomes untestable
12
+ * without launching a real Chromium per assertion, and a suite that needs a
13
+ * browser to test its session bookkeeping is a suite people stop running.
14
+ *
15
+ * ## Derived, not invented
16
+ *
17
+ * Every member below exists because a real export in
18
+ * `descry-runtime/packages/browser/src/index.ts` provides it. The refusal
19
+ * shape is `launchBrowserSessionOrRefuse`'s verbatim; `isUsable()` is
20
+ * `BrowserSession`'s, including its reason for existing (a crashed page
21
+ * still reports `isClosed() === false`, so crash tracking cannot be derived
22
+ * from closure); the action verbs are `BrowserActionCollector`'s; the
23
+ * console and network observations are what the two collectors emit. The
24
+ * port narrows that surface — it does not add to it. Nothing here can be
25
+ * satisfied by the real package only by writing new runtime code, with one
26
+ * disclosed exception, `type()` below.
27
+ *
28
+ * ## What the port deliberately does not carry
29
+ *
30
+ * A verdict. There is no `severity`, no `isBug`, no `category` on any
31
+ * observation, because `DEC-381` rules that
32
+ * classification stays in the desktop pipeline. That is enforced structurally
33
+ * rather than by convention: a tool cannot report a triaged finding through
34
+ * a port that has nowhere to put one.
35
+ *
36
+ * Rule 1 holds here as everywhere — nothing in this file names a language, a
37
+ * framework, or a file extension.
38
+ */
39
+ /** A request that did not succeed. Mechanical, not a judgement: no response, or a 4xx/5xx status. */
40
+ export function isFailedRequest(request) {
41
+ return request.status === null || request.status >= 400;
42
+ }
43
+ export const EMPTY_OBSERVATION = { actions: [], consoleErrors: [], requests: [] };
44
+ /** The browser died. Distinct from a closed session: a crash invalidates the id rather than ending it cleanly. */
45
+ export class BrowserSessionCrashedError extends Error {
46
+ sessionId;
47
+ constructor(sessionId) {
48
+ super(`Browser session ${sessionId} is no longer usable — the browser process crashed or the page closed. ` +
49
+ "The session id is invalidated; start a new session. It is deliberately not reopened against a " +
50
+ "different browser, which would silently change what later evidence refers to.");
51
+ this.name = "BrowserSessionCrashedError";
52
+ this.sessionId = sessionId;
53
+ }
54
+ }
55
+ /**
56
+ * The ref named no element in the current snapshot.
57
+ *
58
+ * Thrown for an invented ref **and** for a ref from a superseded snapshot,
59
+ * because those are the same mistake: acting on an element the agent has not
60
+ * seen. Falling back to the stale selector would let a click land on whatever
61
+ * now matches it on a page the caller has never inspected.
62
+ */
63
+ export class UnknownElementRefError extends Error {
64
+ constructor(ref) {
65
+ super(`"${ref}" is not an element in this session's current snapshot. Refs are issued per snapshot and are ` +
66
+ "invalidated by navigation — call browser_snapshot and use a ref from the result.");
67
+ this.name = "UnknownElementRefError";
68
+ }
69
+ }
70
+ //# sourceMappingURL=driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/browser/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAyFH,qGAAqG;AACrG,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,OAAO,OAAO,CAAC,MAAM,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC;AAC1D,CAAC;AAiBD,MAAM,CAAC,MAAM,iBAAiB,GAAuB,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AA0BtG,kHAAkH;AAClH,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC1C,SAAS,CAAS;IAE3B,YAAY,SAAiB;QAC3B,KAAK,CACH,mBAAmB,SAAS,yEAAyE;YACnG,gGAAgG;YAChG,+EAA+E,CAClF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;QACzC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,YAAY,GAAW;QACrB,KAAK,CACH,IAAI,GAAG,+FAA+F;YACpG,kFAAkF,CACrF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * How a browser observation becomes part of a tool reply — §5.3.
3
+ *
4
+ * Two rules live here rather than in each of the seven tools, because seven
5
+ * copies of a disclosure is seven chances for one of them to be missing.
6
+ *
7
+ * **Attached, not fetched.** Evidence rides on the reply for the action that
8
+ * produced it. A separate `browser_get_evidence` would make the caller
9
+ * correlate two replies to learn that its own click caused the error, and
10
+ * would let it skip the second call entirely.
11
+ *
12
+ * **Raw, and disclosed as raw.** Per
13
+ * `DEC-381`, nothing here classifies. The
14
+ * note below is not decoration: a calling agent that receives a console error
15
+ * has to know Descry is not claiming it is a bug, or it will report Descry as
16
+ * having said so.
17
+ */
18
+ import { type BrowserObservation, type ObservedRequest } from "./driver.ts";
19
+ export interface BrowserEvidenceReport {
20
+ readonly consoleErrors: BrowserObservation["consoleErrors"];
21
+ /**
22
+ * The requests that did not succeed, listed.
23
+ *
24
+ * Narrowed from everything the page issued, because a page load can issue
25
+ * fifty requests and a reply that lists every stylesheet is a reply nobody
26
+ * reads. The narrowing is mechanical — no response, or a 4xx/5xx — and it
27
+ * is **only a narrowing of the reply**: the correlation that mints R4 edges
28
+ * runs over every request, since a successful call is exactly what proves a
29
+ * frontend action reached a backend route.
30
+ */
31
+ readonly failedRequests: readonly ObservedRequest[];
32
+ /** How many requests the page issued in total, so the list above is read as a subset and not as all of it. */
33
+ readonly totalRequests: number;
34
+ readonly actions: BrowserObservation["actions"];
35
+ }
36
+ export declare function evidenceReport(observation: BrowserObservation): BrowserEvidenceReport;
37
+ export declare function isEmpty(report: BrowserEvidenceReport): boolean;
38
+ /**
39
+ * The notes any reply carrying evidence must include.
40
+ *
41
+ * The triage disclaimer is emitted **only when there is something to
42
+ * disclaim**. A reply with no errors that solemnly explained it had not
43
+ * triaged them would be noise on the overwhelmingly common path, and noise is
44
+ * how a real disclosure stops being read.
45
+ */
46
+ export declare function evidenceNotes(report: BrowserEvidenceReport): string[];
47
+ //# sourceMappingURL=evidence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../../src/browser/evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAmB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAE7F,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,aAAa,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;IAC5D;;;;;;;;;OASG;IACH,QAAQ,CAAC,cAAc,EAAE,SAAS,eAAe,EAAE,CAAC;IACpD,8GAA8G;IAC9G,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;CACjD;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,kBAAkB,GAAG,qBAAqB,CAOrF;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAE9D;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,EAAE,CAsBrE"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * How a browser observation becomes part of a tool reply — §5.3.
3
+ *
4
+ * Two rules live here rather than in each of the seven tools, because seven
5
+ * copies of a disclosure is seven chances for one of them to be missing.
6
+ *
7
+ * **Attached, not fetched.** Evidence rides on the reply for the action that
8
+ * produced it. A separate `browser_get_evidence` would make the caller
9
+ * correlate two replies to learn that its own click caused the error, and
10
+ * would let it skip the second call entirely.
11
+ *
12
+ * **Raw, and disclosed as raw.** Per
13
+ * `DEC-381`, nothing here classifies. The
14
+ * note below is not decoration: a calling agent that receives a console error
15
+ * has to know Descry is not claiming it is a bug, or it will report Descry as
16
+ * having said so.
17
+ */
18
+ import { isFailedRequest } from "./driver.js";
19
+ export function evidenceReport(observation) {
20
+ return {
21
+ consoleErrors: observation.consoleErrors,
22
+ failedRequests: observation.requests.filter(isFailedRequest),
23
+ totalRequests: observation.requests.length,
24
+ actions: observation.actions,
25
+ };
26
+ }
27
+ export function isEmpty(report) {
28
+ return report.consoleErrors.length === 0 && report.failedRequests.length === 0;
29
+ }
30
+ /**
31
+ * The notes any reply carrying evidence must include.
32
+ *
33
+ * The triage disclaimer is emitted **only when there is something to
34
+ * disclaim**. A reply with no errors that solemnly explained it had not
35
+ * triaged them would be noise on the overwhelmingly common path, and noise is
36
+ * how a real disclosure stops being read.
37
+ */
38
+ export function evidenceNotes(report) {
39
+ if (isEmpty(report))
40
+ return [];
41
+ const notes = [
42
+ `${report.consoleErrors.length} console error(s) and ${report.failedRequests.length} failed request(s) ` +
43
+ "were observed in the browser during this call. They are reported raw and have not been triaged — " +
44
+ "Descry is not claiming any of them is a bug, only that the page produced them. Deciding which " +
45
+ "matter is the calling agent's job.",
46
+ ];
47
+ const unmapped = [...report.consoleErrors, ...report.failedRequests].filter((item) => item.stackText !== null && !item.stackText.startsWith("/") && item.stackText.includes("http")).length;
48
+ if (unmapped > 0) {
49
+ notes.push(`${unmapped} stack trace(s) still name script URLs rather than repository files. Mapping them back ` +
50
+ "to real files and lines needs the browser backend's source-root resolver, which this build does " +
51
+ "not have wired yet, so the raw text is passed through rather than a guess being printed.");
52
+ }
53
+ return notes;
54
+ }
55
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/browser/evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,eAAe,EAAiD,MAAM,aAAa,CAAC;AAoB7F,MAAM,UAAU,cAAc,CAAC,WAA+B;IAC5D,OAAO;QACL,aAAa,EAAE,WAAW,CAAC,aAAa;QACxC,cAAc,EAAE,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,CAAC;QAC5D,aAAa,EAAE,WAAW,CAAC,QAAQ,CAAC,MAAM;QAC1C,OAAO,EAAE,WAAW,CAAC,OAAO;KAC7B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,MAA6B;IACnD,OAAO,MAAM,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,CAAC;AACjF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,MAA6B;IACzD,IAAI,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IAE/B,MAAM,KAAK,GAAG;QACZ,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,yBAAyB,MAAM,CAAC,cAAc,CAAC,MAAM,qBAAqB;YACtG,mGAAmG;YACnG,gGAAgG;YAChG,oCAAoC;KACvC,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,GAAG,MAAM,CAAC,aAAa,EAAE,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,CACzE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CACxG,CAAC,MAAM,CAAC;IACT,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CACR,GAAG,QAAQ,yFAAyF;YAClG,kGAAkG;YAClG,0FAA0F,CAC7F,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * A `BrowserDriver` with no browser behind it.
3
+ *
4
+ * Not a stub. It implements every rule the port states — ref issuance and
5
+ * invalidation, drain-not-peek, crash invalidation, idempotent close that
6
+ * still flushes — and `browser-driver-contract.test.ts` runs the same
7
+ * assertions against it that the real driver will have to pass. Its purpose
8
+ * is to make those rules *checkable in milliseconds*, so the session
9
+ * lifecycle in §4 is tested against timeouts, disconnects and crashes that
10
+ * would otherwise each need a real Chromium.
11
+ *
12
+ * Two deliberate non-goals. It does not simulate a page — pages are declared
13
+ * with `setPage`, because a fake DOM would be a second, wrong browser. And it
14
+ * does not classify anything, for the same structural reason the port does
15
+ * not: there is nowhere to put a verdict.
16
+ */
17
+ import { type BrowserDriver, type ObservedRequest } from "./driver.ts";
18
+ /** A page as a test declares it. `ref` is issued by the fake, not written here. */
19
+ export interface FakePage {
20
+ readonly url: string;
21
+ readonly title: string;
22
+ readonly elements: readonly {
23
+ readonly role: string;
24
+ readonly name: string;
25
+ readonly selector: string;
26
+ }[];
27
+ }
28
+ export interface FakeBrowserDriver extends BrowserDriver {
29
+ /** Declare what is served at `url`. Navigating anywhere undeclared yields an empty page, not an error — an empty page is a real thing a URL can serve. */
30
+ setPage(url: string, page: FakePage): void;
31
+ /** Every subsequent launch refuses, in `launchBrowserSessionOrRefuse`'s shape. */
32
+ setChromiumMissing(remedy?: string): void;
33
+ emitConsoleError(sessionId: string, error: {
34
+ readonly text: string;
35
+ readonly stackText: string | null;
36
+ }): void;
37
+ /** Record a request the page issued. Status and stack are whatever the test needs them to be. */
38
+ emitRequest(sessionId: string, request: {
39
+ readonly method: string;
40
+ readonly url: string;
41
+ readonly status: number | null;
42
+ readonly stackText: string | null;
43
+ readonly stackTrace?: ObservedRequest["stackTrace"];
44
+ }): void;
45
+ /** Sugar for `emitRequest` with a failing status. */
46
+ emitFailedRequest(sessionId: string, request: {
47
+ readonly method: string;
48
+ readonly url: string;
49
+ readonly status: number | null;
50
+ readonly stackText: string | null;
51
+ }): void;
52
+ /** Kill the browser behind a session, the way a real crash does — usable goes false, the id stays invalid. */
53
+ crash(sessionId: string): void;
54
+ /** Every session this driver has opened and not closed. What the registry's orphan-cleanup tests assert against. */
55
+ openSessionIds(): readonly string[];
56
+ }
57
+ export declare function createFakeBrowserDriver(): FakeBrowserDriver;
58
+ //# sourceMappingURL=fake-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-driver.d.ts","sourceRoot":"","sources":["../../src/browser/fake-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAGL,KAAK,aAAa,EAOlB,KAAK,eAAe,EAGrB,MAAM,aAAa,CAAC;AAErB,mFAAmF;AACnF,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3G;AAED,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,0JAA0J;IAC1J,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3C,kFAAkF;IAClF,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/G,iGAAiG;IACjG,WAAW,CACT,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;QACP,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;KACrD,GACA,IAAI,CAAC;IACR,qDAAqD;IACrD,iBAAiB,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAC5H,IAAI,CAAC;IACR,8GAA8G;IAC9G,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oHAAoH;IACpH,cAAc,IAAI,SAAS,MAAM,EAAE,CAAC;CACrC;AAeD,wBAAgB,uBAAuB,IAAI,iBAAiB,CAsJ3D"}