@serfab/cadre-core 1.17.0 → 1.19.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 (148) hide show
  1. package/README.md +3 -2
  2. package/dist/cadre-invite-protocol.d.ts +35 -13
  3. package/dist/cadre-invite-protocol.js +90 -25
  4. package/dist/cadre-invite-protocol.js.map +1 -1
  5. package/dist/cadre-node.d.ts +586 -255
  6. package/dist/cadre-node.js +1182 -566
  7. package/dist/cadre-node.js.map +1 -1
  8. package/dist/control-cohort.d.ts +66 -9
  9. package/dist/control-cohort.js +67 -9
  10. package/dist/control-cohort.js.map +1 -1
  11. package/dist/control-database.d.ts +451 -193
  12. package/dist/control-database.js +701 -359
  13. package/dist/control-database.js.map +1 -1
  14. package/dist/control-formation-recorder.d.ts +46 -43
  15. package/dist/control-formation-recorder.js +77 -78
  16. package/dist/control-formation-recorder.js.map +1 -1
  17. package/dist/control-protocol-guard.d.ts +6 -0
  18. package/dist/control-protocol-guard.js +14 -2
  19. package/dist/control-protocol-guard.js.map +1 -1
  20. package/dist/control-schema-version.d.ts +48 -31
  21. package/dist/control-schema-version.js +67 -45
  22. package/dist/control-schema-version.js.map +1 -1
  23. package/dist/control-schema.d.ts +8 -8
  24. package/dist/control-schema.js +16 -16
  25. package/dist/control-schema.js.map +1 -1
  26. package/dist/control-write-retry.d.ts +42 -7
  27. package/dist/control-write-retry.js +87 -19
  28. package/dist/control-write-retry.js.map +1 -1
  29. package/dist/enrolled-machine-store.d.ts +3 -3
  30. package/dist/enrolled-machine-store.js +3 -3
  31. package/dist/formation-token.d.ts +48 -0
  32. package/dist/formation-token.js +26 -0
  33. package/dist/formation-token.js.map +1 -0
  34. package/dist/index.d.ts +15 -14
  35. package/dist/index.js +17 -14
  36. package/dist/index.js.map +1 -1
  37. package/dist/joined-strand-store.d.ts +26 -9
  38. package/dist/joined-strand-store.js +63 -24
  39. package/dist/joined-strand-store.js.map +1 -1
  40. package/dist/link-budget.d.ts +9 -7
  41. package/dist/link-budget.js +9 -7
  42. package/dist/link-budget.js.map +1 -1
  43. package/dist/member-redemption.d.ts +15 -9
  44. package/dist/member-redemption.js +13 -8
  45. package/dist/member-redemption.js.map +1 -1
  46. package/dist/membership-view.d.ts +91 -0
  47. package/dist/membership-view.js +110 -0
  48. package/dist/membership-view.js.map +1 -0
  49. package/dist/owner-grant-protocol.d.ts +11 -7
  50. package/dist/owner-grant-protocol.js +31 -17
  51. package/dist/owner-grant-protocol.js.map +1 -1
  52. package/dist/peer-addr-book.d.ts +10 -1
  53. package/dist/peer-addr-book.js +4 -3
  54. package/dist/peer-addr-book.js.map +1 -1
  55. package/dist/peer-join-backfill.d.ts +96 -30
  56. package/dist/peer-join-backfill.js +272 -128
  57. package/dist/peer-join-backfill.js.map +1 -1
  58. package/dist/pending-join-runner.d.ts +48 -18
  59. package/dist/pending-join-runner.js +74 -56
  60. package/dist/pending-join-runner.js.map +1 -1
  61. package/dist/seed-bootstrap.d.ts +47 -40
  62. package/dist/seed-bootstrap.js +66 -61
  63. package/dist/seed-bootstrap.js.map +1 -1
  64. package/dist/self-address-update.d.ts +13 -0
  65. package/dist/self-address-update.js +19 -0
  66. package/dist/self-address-update.js.map +1 -0
  67. package/dist/strand-database.d.ts +23 -2
  68. package/dist/strand-database.js +26 -6
  69. package/dist/strand-database.js.map +1 -1
  70. package/dist/strand-first-sync-gate.d.ts +176 -89
  71. package/dist/strand-first-sync-gate.js +288 -122
  72. package/dist/strand-first-sync-gate.js.map +1 -1
  73. package/dist/strand-formation-deadlines.d.ts +9 -9
  74. package/dist/strand-formation-deadlines.js +9 -9
  75. package/dist/strand-formation-manager.d.ts +23 -17
  76. package/dist/strand-formation-manager.js +46 -44
  77. package/dist/strand-formation-manager.js.map +1 -1
  78. package/dist/strand-formation-protocol.d.ts +5 -8
  79. package/dist/strand-formation-protocol.js +101 -16
  80. package/dist/strand-formation-protocol.js.map +1 -1
  81. package/dist/strand-instance-manager.d.ts +26 -17
  82. package/dist/strand-instance-manager.js +119 -50
  83. package/dist/strand-instance-manager.js.map +1 -1
  84. package/dist/strand-membership-reconciler.d.ts +16 -13
  85. package/dist/strand-membership-reconciler.js +28 -22
  86. package/dist/strand-membership-reconciler.js.map +1 -1
  87. package/dist/strand-membership-writer.d.ts +40 -28
  88. package/dist/strand-membership-writer.js +212 -153
  89. package/dist/strand-membership-writer.js.map +1 -1
  90. package/dist/strand-move.js +5 -2
  91. package/dist/strand-move.js.map +1 -1
  92. package/dist/strand-revocation-enforcer.d.ts +134 -60
  93. package/dist/strand-revocation-enforcer.js +144 -71
  94. package/dist/strand-revocation-enforcer.js.map +1 -1
  95. package/dist/strand-solicitation.d.ts +50 -39
  96. package/dist/strand-solicitation.js +10 -3
  97. package/dist/strand-solicitation.js.map +1 -1
  98. package/dist/strand-watcher.d.ts +80 -13
  99. package/dist/strand-watcher.js +152 -48
  100. package/dist/strand-watcher.js.map +1 -1
  101. package/dist/table-change-watch.d.ts +63 -0
  102. package/dist/table-change-watch.js +209 -0
  103. package/dist/table-change-watch.js.map +1 -0
  104. package/dist/timeout-scheduler.d.ts +4 -3
  105. package/dist/timeout-scheduler.js +4 -3
  106. package/dist/timeout-scheduler.js.map +1 -1
  107. package/dist/types.d.ts +90 -49
  108. package/dist/types.js +4 -4
  109. package/dist/types.js.map +1 -1
  110. package/package.json +8 -8
  111. package/src/cadre-invite-protocol.ts +119 -31
  112. package/src/cadre-node.ts +1289 -588
  113. package/src/control-cohort.ts +86 -9
  114. package/src/control-database.ts +848 -403
  115. package/src/control-formation-recorder.ts +359 -353
  116. package/src/control-protocol-guard.ts +16 -2
  117. package/src/control-schema-version.ts +101 -51
  118. package/src/control-schema.ts +16 -16
  119. package/src/control-write-retry.ts +91 -19
  120. package/src/delegate-admission.ts +351 -351
  121. package/src/enrolled-machine-store.ts +3 -3
  122. package/src/formation-token.ts +63 -0
  123. package/src/index.ts +30 -18
  124. package/src/joined-strand-store.ts +69 -24
  125. package/src/link-budget.ts +9 -7
  126. package/src/member-redemption.ts +20 -13
  127. package/src/membership-view.ts +144 -0
  128. package/src/owner-grant-protocol.ts +33 -18
  129. package/src/peer-addr-book.ts +4 -3
  130. package/src/peer-join-backfill.ts +961 -761
  131. package/src/pending-join-runner.ts +76 -53
  132. package/src/seed-bootstrap.ts +72 -67
  133. package/src/self-address-update.ts +19 -0
  134. package/src/strand-database.ts +352 -322
  135. package/src/strand-first-sync-gate.ts +334 -134
  136. package/src/strand-formation-deadlines.ts +227 -227
  137. package/src/strand-formation-manager.ts +731 -725
  138. package/src/strand-formation-protocol.ts +122 -24
  139. package/src/strand-instance-manager.ts +2092 -2026
  140. package/src/strand-membership-reconciler.ts +31 -25
  141. package/src/strand-membership-writer.ts +2093 -2019
  142. package/src/strand-move.ts +5 -2
  143. package/src/strand-revocation-enforcer.ts +740 -654
  144. package/src/strand-solicitation.ts +61 -34
  145. package/src/strand-watcher.ts +175 -56
  146. package/src/table-change-watch.ts +285 -0
  147. package/src/timeout-scheduler.ts +29 -28
  148. package/src/types.ts +89 -51
@@ -22,17 +22,44 @@
22
22
  */
23
23
  import type { CohortPeerRow } from './strand-cohort.js';
24
24
  /**
25
- * Default recurring cadence for {@link CadreNode.reconcileControlCohort} (ms).
26
- * In the same spirit as the 5s strand-watch poll but lighter, since a control
27
- * cohort changes far less often than strand activity.
25
+ * Default backstop for {@link CadreNode.reconcileControlCohort} (ms): a pass runs this long
26
+ * after the last one settled whether or not anything woke it. Passes normally run on a
27
+ * change — a membership table changing, a sibling connecting or disconnecting, an address
28
+ * change — and on the retries a pass arms for itself ({@link nextReconcileWakeMs}); the
29
+ * backstop bounds how stale this node can be after a change it hears nothing of: one that
30
+ * reaches it with no storage event, which happens to a machine outside the block's cohort
31
+ * (a cadre larger than `CONTROL_REPLICATION_BREADTH`) and to one in the cohort that the
32
+ * writer could not reach when it committed. The membership rows view's maximum age
33
+ * (`MEMBERSHIP_VIEW_MAX_AGE_MS`, 15 s) is shorter than this, so the backstop pass reads
34
+ * storage and starts the cohort consult that brings such a change in.
28
35
  *
29
- * An interval between pass starts, not a deadline on a pass. Passes are
30
- * single-flight, so a pass that runs longer than this is joined rather than
31
- * stacked, and the effective cadence becomes the pass length: one unreachable
32
- * sibling's dial alone can take the whole per-peer dial budget (86 s at the
33
- * default declared link).
36
+ * `network.controlCohort.reconcileMs` overrides it. An interval between a pass settling and
37
+ * the next start, not a deadline on a pass: passes are single-flight, and one unreachable
38
+ * sibling's dial alone can take the whole per-peer dial budget (86 s at the default
39
+ * declared link).
40
+ *
41
+ * NOTE: a machine whose storage takes no event for a change — one outside the block's cohort
42
+ * in a cadre larger than `CONTROL_REPLICATION_BREADTH` (16 machines), or one the writer could
43
+ * not reach when it committed — sees it only at this backstop, where the change-driven path
44
+ * serves a machine the commit reached within the 50 ms coalescing window. If a party ever
45
+ * needs a tighter bound, lower the backstop for its nodes or give the plugin's change bridge
46
+ * a path for outside-the-cohort reads.
47
+ */
48
+ export declare const DEFAULT_CONTROL_COHORT_RECONCILE_MS = 120000;
49
+ /**
50
+ * First redial delay after a pass's dial of a selected sibling, or a cold-start bootstrap peer,
51
+ * fails (ms). Doubles per consecutive such pass and is capped at the backstop, so a
52
+ * sibling that is offline costs one dial per backstop once the ladder saturates, and a
53
+ * stranded cold-start node keeps trying forever (15 s, 30 s, 60 s, then every backstop).
34
54
  */
35
- export declare const DEFAULT_CONTROL_COHORT_RECONCILE_MS = 15000;
55
+ export declare const CONTROL_COHORT_REDIAL_MS = 15000;
56
+ /**
57
+ * How often an owner retries a node it has just claimed while that node restarts into the
58
+ * owner's party (ms; `CadreNode.claimNode`). A poll step, not a deadline: the retries run for
59
+ * {@link CONTROL_COHORT_REDIAL_MS} after the node accepts the claim, the delay of the reconcile
60
+ * pass's first redial, which would otherwise be the owner's next dial of the node.
61
+ */
62
+ export declare const CLAIM_RESTART_REDIAL_STEP_MS = 1000;
36
63
  /**
37
64
  * Default cap on the number of **non-backbone** members a single reconcile pass
38
65
  * proactively dials. Backbone (always-on) members are always dialed and do NOT
@@ -79,3 +106,33 @@ export interface ControlCohortReconcileResult {
79
106
  * @param targetDegree - cap on non-backbone dials (negative is treated as 0).
80
107
  */
81
108
  export declare function selectControlCohortDials(siblings: CohortPeerRow[], targetDegree: number): ControlCohortSelection;
109
+ /** What {@link nextReconcileWakeMs} decides from, all times epoch milliseconds. */
110
+ export interface ReconcileWakeInput {
111
+ /**
112
+ * Consecutive passes, this one included, whose dial of a selected sibling or a cold-start
113
+ * bootstrap peer failed; 0 when none of this pass's dials did.
114
+ */
115
+ redialStreak: number;
116
+ /** When the pass that just ended began. */
117
+ passStartedAt: number;
118
+ /** Every (sibling, strand) strand-address due time this node holds. */
119
+ strandAddrDueAt: Iterable<number>;
120
+ now: number;
121
+ /** The scheduler's backstop (ms); no wake is later than it. */
122
+ backstopMs: number;
123
+ }
124
+ /**
125
+ * How long after a pass the next one should run for the pass's own reasons, or `undefined`
126
+ * when the backstop covers everything:
127
+ *
128
+ * - **Redial.** A streak of unconnected passes wakes after
129
+ * `min(CONTROL_COHORT_REDIAL_MS × 2^(streak − 1), backstop)`.
130
+ * - **Strand addresses.** The earliest strand-address due time LATER THAN the pass's start,
131
+ * when it is sooner than the backstop, wakes when it falls due (now at the latest). A due
132
+ * time at or before the start belongs to a (sibling, strand) the pass skipped for another
133
+ * reason — the strand stopped, the sibling disconnected — and waking for it would spin; the
134
+ * strand watcher's launch retry keeps the same rule.
135
+ *
136
+ * The smaller wins.
137
+ */
138
+ export declare function nextReconcileWakeMs(input: ReconcileWakeInput): number | undefined;
@@ -21,17 +21,44 @@
21
21
  * party it bounds out-degree to `backbone + targetDegree`.
22
22
  */
23
23
  /**
24
- * Default recurring cadence for {@link CadreNode.reconcileControlCohort} (ms).
25
- * In the same spirit as the 5s strand-watch poll but lighter, since a control
26
- * cohort changes far less often than strand activity.
24
+ * Default backstop for {@link CadreNode.reconcileControlCohort} (ms): a pass runs this long
25
+ * after the last one settled whether or not anything woke it. Passes normally run on a
26
+ * change — a membership table changing, a sibling connecting or disconnecting, an address
27
+ * change — and on the retries a pass arms for itself ({@link nextReconcileWakeMs}); the
28
+ * backstop bounds how stale this node can be after a change it hears nothing of: one that
29
+ * reaches it with no storage event, which happens to a machine outside the block's cohort
30
+ * (a cadre larger than `CONTROL_REPLICATION_BREADTH`) and to one in the cohort that the
31
+ * writer could not reach when it committed. The membership rows view's maximum age
32
+ * (`MEMBERSHIP_VIEW_MAX_AGE_MS`, 15 s) is shorter than this, so the backstop pass reads
33
+ * storage and starts the cohort consult that brings such a change in.
27
34
  *
28
- * An interval between pass starts, not a deadline on a pass. Passes are
29
- * single-flight, so a pass that runs longer than this is joined rather than
30
- * stacked, and the effective cadence becomes the pass length: one unreachable
31
- * sibling's dial alone can take the whole per-peer dial budget (86 s at the
32
- * default declared link).
35
+ * `network.controlCohort.reconcileMs` overrides it. An interval between a pass settling and
36
+ * the next start, not a deadline on a pass: passes are single-flight, and one unreachable
37
+ * sibling's dial alone can take the whole per-peer dial budget (86 s at the default
38
+ * declared link).
39
+ *
40
+ * NOTE: a machine whose storage takes no event for a change — one outside the block's cohort
41
+ * in a cadre larger than `CONTROL_REPLICATION_BREADTH` (16 machines), or one the writer could
42
+ * not reach when it committed — sees it only at this backstop, where the change-driven path
43
+ * serves a machine the commit reached within the 50 ms coalescing window. If a party ever
44
+ * needs a tighter bound, lower the backstop for its nodes or give the plugin's change bridge
45
+ * a path for outside-the-cohort reads.
46
+ */
47
+ export const DEFAULT_CONTROL_COHORT_RECONCILE_MS = 120000;
48
+ /**
49
+ * First redial delay after a pass's dial of a selected sibling, or a cold-start bootstrap peer,
50
+ * fails (ms). Doubles per consecutive such pass and is capped at the backstop, so a
51
+ * sibling that is offline costs one dial per backstop once the ladder saturates, and a
52
+ * stranded cold-start node keeps trying forever (15 s, 30 s, 60 s, then every backstop).
33
53
  */
34
- export const DEFAULT_CONTROL_COHORT_RECONCILE_MS = 15000;
54
+ export const CONTROL_COHORT_REDIAL_MS = 15000;
55
+ /**
56
+ * How often an owner retries a node it has just claimed while that node restarts into the
57
+ * owner's party (ms; `CadreNode.claimNode`). A poll step, not a deadline: the retries run for
58
+ * {@link CONTROL_COHORT_REDIAL_MS} after the node accepts the claim, the delay of the reconcile
59
+ * pass's first redial, which would otherwise be the owner's next dial of the node.
60
+ */
61
+ export const CLAIM_RESTART_REDIAL_STEP_MS = 1000;
35
62
  /**
36
63
  * Default cap on the number of **non-backbone** members a single reconcile pass
37
64
  * proactively dials. Backbone (always-on) members are always dialed and do NOT
@@ -83,4 +110,35 @@ export function selectControlCohortDials(siblings, targetDegree) {
83
110
  cappedNonBackbone: rest.length - fill.length,
84
111
  };
85
112
  }
113
+ /**
114
+ * How long after a pass the next one should run for the pass's own reasons, or `undefined`
115
+ * when the backstop covers everything:
116
+ *
117
+ * - **Redial.** A streak of unconnected passes wakes after
118
+ * `min(CONTROL_COHORT_REDIAL_MS × 2^(streak − 1), backstop)`.
119
+ * - **Strand addresses.** The earliest strand-address due time LATER THAN the pass's start,
120
+ * when it is sooner than the backstop, wakes when it falls due (now at the latest). A due
121
+ * time at or before the start belongs to a (sibling, strand) the pass skipped for another
122
+ * reason — the strand stopped, the sibling disconnected — and waking for it would spin; the
123
+ * strand watcher's launch retry keeps the same rule.
124
+ *
125
+ * The smaller wins.
126
+ */
127
+ export function nextReconcileWakeMs(input) {
128
+ const { redialStreak, passStartedAt, strandAddrDueAt, now, backstopMs } = input;
129
+ let wake;
130
+ if (redialStreak > 0) {
131
+ wake = Math.min(CONTROL_COHORT_REDIAL_MS * 2 ** (redialStreak - 1), backstopMs);
132
+ }
133
+ for (const dueAt of strandAddrDueAt) {
134
+ if (dueAt <= passStartedAt) {
135
+ continue;
136
+ }
137
+ const delay = Math.max(0, dueAt - now);
138
+ if (delay < backstopMs && (wake === undefined || delay < wake)) {
139
+ wake = delay;
140
+ }
141
+ }
142
+ return wake;
143
+ }
86
144
  //# sourceMappingURL=control-cohort.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"control-cohort.js","sourceRoot":"","sources":["../src/control-cohort.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,KAAM,CAAC;AAE1D;;;;GAIG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC,CAAC;AAkCtD,mFAAmF;AACnF,SAAS,QAAQ,CAAC,CAAgB,EAAE,CAAgB;IAClD,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAyB,EACzB,YAAoB;IAEpB,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,IAAI,GAAoB,EAAE,CAAC;IAEjC,mFAAmF;IACnF,wFAAwF;IACxF,uDAAuD;IACvD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC/B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEhC,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC;QAC7B,iBAAiB,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM;KAC7C,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"control-cohort.js","sourceRoot":"","sources":["../src/control-cohort.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,MAAO,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAM,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAK,CAAC;AAElD;;;;GAIG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC,CAAC;AAkCtD,mFAAmF;AACnF,SAAS,QAAQ,CAAC,CAAgB,EAAE,CAAgB;IAClD,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAyB,EACzB,YAAoB;IAEpB,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,IAAI,GAAoB,EAAE,CAAC;IAEjC,mFAAmF;IACnF,wFAAwF;IACxF,uDAAuD;IACvD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC/B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEhC,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC;QAC7B,iBAAiB,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM;KAC7C,CAAC;AACJ,CAAC;AAkBD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAyB;IAC3D,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAChF,IAAI,IAAwB,CAAC;IAC7B,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,wBAAwB,GAAG,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAClF,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QACpC,IAAI,KAAK,IAAI,aAAa,EAAE,CAAC;YAC3B,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,GAAG,CAAC,CAAC;QACvC,IAAI,KAAK,GAAG,UAAU,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC;YAC/D,IAAI,GAAG,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}