@trillboards/edge-sdk 0.2.39 → 0.2.41

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 (82) hide show
  1. package/README.md +1 -1
  2. package/deploy/docker/{Dockerfile.cloud-sense → Dockerfile.connector} +52 -39
  3. package/deploy/docker/README.md +73 -1
  4. package/deploy/docker/connector-entrypoint.sh +46 -80
  5. package/deploy/macos/README.md +1 -1
  6. package/deploy/macos/test-install-pair.sh +9 -9
  7. package/deploy/systemd/install.sh +16 -1
  8. package/deploy/systemd/setup-litertlm.sh +201 -0
  9. package/deploy/systemd/trillboards-edge.service +8 -4
  10. package/deploy/systemd/trillboards-litertlm.service +46 -0
  11. package/deploy/windows/register-task.ps1 +6 -3
  12. package/deploy/windows/run-connector.ps1 +1 -1
  13. package/deploy/windows/trillboards-edge-task.vbs +5 -1
  14. package/dist/CloudSensingManager.d.ts +45 -19
  15. package/dist/CloudSensingManager.d.ts.map +1 -1
  16. package/dist/CloudSensingManager.js +89 -46
  17. package/dist/CloudSensingManager.js.map +1 -1
  18. package/dist/EdgeAgent.js +1 -1
  19. package/dist/SensingProfileClient.d.ts +9 -0
  20. package/dist/SensingProfileClient.d.ts.map +1 -1
  21. package/dist/SensingProfileClient.js +4 -0
  22. package/dist/SensingProfileClient.js.map +1 -1
  23. package/dist/SetupSessionClient.d.ts +0 -1
  24. package/dist/SetupSessionClient.d.ts.map +1 -1
  25. package/dist/autoSense.d.ts +42 -31
  26. package/dist/autoSense.d.ts.map +1 -1
  27. package/dist/autoSense.js +127 -99
  28. package/dist/autoSense.js.map +1 -1
  29. package/dist/cli.d.ts.map +1 -1
  30. package/dist/cli.js +25 -84
  31. package/dist/cli.js.map +1 -1
  32. package/dist/combinedSense.d.ts +1 -3
  33. package/dist/combinedSense.d.ts.map +1 -1
  34. package/dist/combinedSense.js +0 -1
  35. package/dist/combinedSense.js.map +1 -1
  36. package/dist/config.d.ts +17 -64
  37. package/dist/config.d.ts.map +1 -1
  38. package/dist/config.js +0 -10
  39. package/dist/config.js.map +1 -1
  40. package/dist/deployedCadence.d.ts +37 -75
  41. package/dist/deployedCadence.d.ts.map +1 -1
  42. package/dist/deployedCadence.js +45 -105
  43. package/dist/deployedCadence.js.map +1 -1
  44. package/dist/deployedCadenceSource.d.ts +0 -2
  45. package/dist/deployedCadenceSource.d.ts.map +1 -1
  46. package/dist/deployedCadenceSource.js +0 -1
  47. package/dist/deployedCadenceSource.js.map +1 -1
  48. package/dist/diagnose.d.ts +1 -1
  49. package/dist/diagnose.js +1 -1
  50. package/dist/index.d.ts +0 -3
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +1 -8
  53. package/dist/index.js.map +1 -1
  54. package/dist/localInferenceSchema.d.ts +19 -0
  55. package/dist/localInferenceSchema.d.ts.map +1 -1
  56. package/dist/localInferenceSchema.js +23 -0
  57. package/dist/localInferenceSchema.js.map +1 -1
  58. package/dist/localSensing.d.ts +48 -107
  59. package/dist/localSensing.d.ts.map +1 -1
  60. package/dist/localSensing.js +80 -171
  61. package/dist/localSensing.js.map +1 -1
  62. package/dist/sensingCatchRate.d.ts +246 -0
  63. package/dist/sensingCatchRate.d.ts.map +1 -0
  64. package/dist/sensingCatchRate.js +514 -0
  65. package/dist/sensingCatchRate.js.map +1 -0
  66. package/dist/sensingRunMode.d.ts +14 -11
  67. package/dist/sensingRunMode.d.ts.map +1 -1
  68. package/dist/sensingRunMode.js +9 -92
  69. package/dist/sensingRunMode.js.map +1 -1
  70. package/dist/setupMode.d.ts +0 -1
  71. package/dist/setupMode.d.ts.map +1 -1
  72. package/dist/setupMode.js +5 -3
  73. package/dist/setupMode.js.map +1 -1
  74. package/dist/startupDiscovery.d.ts +43 -0
  75. package/dist/startupDiscovery.d.ts.map +1 -0
  76. package/dist/startupDiscovery.js +72 -0
  77. package/dist/startupDiscovery.js.map +1 -0
  78. package/package.json +1 -1
  79. package/dist/CloudEscalationPolicy.d.ts +0 -143
  80. package/dist/CloudEscalationPolicy.d.ts.map +0 -1
  81. package/dist/CloudEscalationPolicy.js +0 -137
  82. package/dist/CloudEscalationPolicy.js.map +0 -1
@@ -0,0 +1,246 @@
1
+ /**
2
+ * The four REPORTING groups. Every table this module produces is grouped by
3
+ * these and never blended across them, because a promise's group determines
4
+ * which failure mode can even occur: an Instant promise fails by never being
5
+ * looked at, a State promise fails by firing on the wrong side of an edge.
6
+ */
7
+ export type ShapeGroup = 'Instant' | 'Brief' | 'Sustained' | 'State';
8
+ export declare const SHAPE_GROUPS: readonly ShapeGroup[];
9
+ /**
10
+ * A temporal shape: what the promise is shaped like in TIME, independent of
11
+ * what it is about. Seven of them cover the live route table.
12
+ *
13
+ * `rulePolicy` is the `sensing_routes.re_fire_policy` a route of this shape
14
+ * carries, and `holdSeconds` is its `sustain_seconds`. Both are named against
15
+ * the real columns so a shape cannot describe a rule the product cannot
16
+ * express — the classification is derived from config that exists, not
17
+ * invented for the eval.
18
+ */
19
+ export interface TemporalShape {
20
+ /** Stable id. Used as the key in every report and in the CI baseline. */
21
+ id: string;
22
+ /** The reporting group. */
23
+ group: ShapeGroup;
24
+ /** Human sentence, in the operator's words. */
25
+ description: string;
26
+ /** Inclusive lower bound on event duration, seconds. */
27
+ minDurationS: number;
28
+ /** Exclusive upper bound on event duration, seconds. `Infinity` for open. */
29
+ maxDurationS: number;
30
+ /** The `sensing_routes.re_fire_policy` this shape is expressed with. */
31
+ rulePolicy: 'once_per_episode' | 'per_new_entity' | 'on_escalation' | 'nag_until_resolved';
32
+ /**
33
+ * Seconds the condition must HOLD before the alert is earned
34
+ * (`sensing_routes.sustain_seconds`). 0 = fires on the rising edge.
35
+ */
36
+ holdSeconds: number;
37
+ /** A live `sensing_routes.condition_field` of this shape, for grounding. */
38
+ exampleField: string;
39
+ }
40
+ /**
41
+ * Seven shapes. Each `exampleField` is a real `condition_field` present in
42
+ * `sensing_routes` in production — this table is a classification of what we
43
+ * already sell, not a wish list.
44
+ *
45
+ * The duration bands are cut where the FAILURE MODE changes, not on round
46
+ * numbers. Below ~3 s a 30 s look cadence misses the event outright. Between
47
+ * 3 s and 30 s the look lands but the single admission slot (7.30 s) may still
48
+ * lose it. Past 30 s at least one look is guaranteed and the question stops
49
+ * being "did we see it" and becomes "did we fire on the right edge".
50
+ */
51
+ export declare const TEMPORAL_SHAPES: readonly TemporalShape[];
52
+ /** Look a shape up by id. `null` — never a throw — for an unknown id. */
53
+ export declare function shapeById(id: string): TemporalShape | null;
54
+ /**
55
+ * The shape of an annotated event.
56
+ *
57
+ * Duration alone does NOT determine the shape: `instant` and `arrival` share a
58
+ * band and are separated by the rule policy, as do `interaction`/`excursion`
59
+ * and `condition`/`absence`. So the corpus must carry the policy, and this
60
+ * function refuses to guess when it is absent rather than silently picking the
61
+ * first band match — a misclassified event lands in the wrong shape's rate and
62
+ * is invisible.
63
+ */
64
+ export declare function classifyShape(durationS: number, rulePolicy: TemporalShape['rulePolicy']): TemporalShape | null;
65
+ /**
66
+ * P(at least one look lands inside an event of `durationS`) for a periodic
67
+ * look cadence of `cadenceS` whose phase is uncorrelated with the event.
68
+ *
69
+ * `min(d/T, 1)`. An event at least as long as the cadence is caught with
70
+ * certainty; a shorter one is caught in proportion to how much of the cadence
71
+ * it occupies. This is the ceiling every other factor multiplies down from.
72
+ */
73
+ export declare function lookCoverage(durationS: number, cadenceS: number): number;
74
+ /**
75
+ * The closed-form catch rate over a whole duration sample: `E[min(d/T, 1)]`.
76
+ *
77
+ * Note this is driven by the MEAN of the truncated ratio, not by the median
78
+ * duration. A right-skewed duration sample — which every real activity corpus
79
+ * is — has a mean well above its median, so quoting `median/T` understates the
80
+ * rate. That is exactly the arithmetic behind the published baseline: 59,093
81
+ * activities with a 2.4 s median catch at 18.2%, not at 2.4/30 = 8.0%.
82
+ */
83
+ export declare function expectedCatchRate(durationsS: readonly number[], cadenceS: number): number | null;
84
+ /** One annotated event: a real interval on a real feed, from the corpus. */
85
+ export interface AnnotatedEvent {
86
+ /** Unique within a corpus. */
87
+ id: string;
88
+ /** Which feed (camera) it happened on. Feeds share ONE admission slot. */
89
+ feed: string;
90
+ /** Event class, e.g. `person_opens_facility_door`. */
91
+ eventClass: string;
92
+ /** Shape id — must be a `TEMPORAL_SHAPES.id`. */
93
+ shapeId: string;
94
+ /** Start, seconds from the start of the replay. */
95
+ startS: number;
96
+ /** End, seconds from the start of the replay. Must be > startS. */
97
+ endS: number;
98
+ /**
99
+ * Does this event produce enough pixel change for `MotionGate` to call it?
100
+ * `false` models the documented still-scene class — a leaking cooler, a
101
+ * hazard nobody created — which contributes ZERO motion analyses and can
102
+ * ONLY be found by the periodic heartbeat (connectorCadence.ts header).
103
+ */
104
+ producesMotion: boolean;
105
+ }
106
+ export interface SamplerConfig {
107
+ /**
108
+ * Look cadence, seconds. The binding constraint. Defaults to the shipped
109
+ * `LOOK_INTERVAL_MS`.
110
+ */
111
+ lookCadenceS: number;
112
+ /**
113
+ * Still-scene heartbeat, seconds. The only thing that can find a
114
+ * `producesMotion: false` event. Defaults to the DOOH periodic default.
115
+ */
116
+ heartbeatS: number;
117
+ /** Concurrent analyses. Local sensing ships exactly ONE. */
118
+ maxInFlight: number;
119
+ /** Seconds one analysis occupies the slot. Defaults to the measured 7.30 s. */
120
+ analyzeS: number;
121
+ /** Candidate-buffer TTL, seconds. A held frame older than this is dropped. */
122
+ bufferTtlS: number;
123
+ /** Max frames the buffer will hold at once, across all feeds. */
124
+ bufferMaxFrames: number;
125
+ /**
126
+ * Probability the model reads a CAUGHT frame correctly, per shape. Supplied
127
+ * by a scored replay (`scoreFields`), never guessed here. `1` isolates the
128
+ * temporal layer.
129
+ */
130
+ fieldAccuracy: number;
131
+ /**
132
+ * Probability an analysis of a frame with NO event in progress nevertheless
133
+ * satisfies the rule — the content-layer false trigger. Also from a scored
134
+ * replay.
135
+ */
136
+ falsePositiveRate: number;
137
+ }
138
+ export declare const DEFAULT_SAMPLER: Readonly<SamplerConfig>;
139
+ /** Per-event replay outcome. */
140
+ export interface EventOutcome {
141
+ id: string;
142
+ shapeId: string;
143
+ eventClass: string;
144
+ /** A look landed inside the event. The ceiling. */
145
+ looked: boolean;
146
+ /** That look's frame reached the model (directly or via the buffer). */
147
+ analyzed: boolean;
148
+ /** The model also read it correctly, so the rule could fire. */
149
+ caught: boolean;
150
+ /**
151
+ * Why it was lost, when it was. These are four DIFFERENT defects with four
152
+ * different fixes, and collapsing them is how someone ends up buying a
153
+ * second inference slot to fix a look-cadence problem.
154
+ * never_looked — no look landed inside the event. Fix: look cadence.
155
+ * gate_dropped — a look landed and MotionGate declined to analyse it.
156
+ * Fix: the heartbeat (this is the still-scene case).
157
+ * slot_starved — the gate approved it and the slot was busy. Fix: slots.
158
+ * buffer_expired— it was held and the TTL ran out. Fix: TTL or slots.
159
+ * model_wrong — it reached the model and the model read it wrong.
160
+ */
161
+ lostTo: 'never_looked' | 'gate_dropped' | 'slot_starved' | 'buffer_expired' | 'model_wrong' | null;
162
+ /** Seconds from event start to the analysis landing. `null` if never. */
163
+ latencyS: number | null;
164
+ }
165
+ export interface ReplayResult {
166
+ outcomes: EventOutcome[];
167
+ /** Analyses spent on frames with no event in progress. */
168
+ idleAnalyses: number;
169
+ /** Idle analyses that nevertheless satisfied a rule — false triggers. */
170
+ falseTriggers: number;
171
+ /** Total analyses run. */
172
+ analyses: number;
173
+ /** Looks taken. Cheap, but not free — this sizes the CPU claim. */
174
+ looks: number;
175
+ }
176
+ /**
177
+ * Replay an annotated corpus through the shipped scheduling law.
178
+ *
179
+ * The loop is the real one, in the real order:
180
+ * look tick per feed (staggered) -> motion gate -> admission slot ->
181
+ * candidate buffer on denial -> pump when the slot frees.
182
+ *
183
+ * `durationS` is the replay length; events must fall inside it. `seed` fixes
184
+ * the per-feed look PHASE, which is the only stochastic input — and it is the
185
+ * one that matters, because a phase locked to the events would manufacture a
186
+ * catch rate of either 0% or 100%.
187
+ */
188
+ export declare function replay(events: readonly AnnotatedEvent[], config: Partial<SamplerConfig> | undefined, { durationS, seed }: {
189
+ durationS: number;
190
+ seed?: number;
191
+ }): ReplayResult;
192
+ export interface ShapeReport {
193
+ shapeId: string;
194
+ group: ShapeGroup;
195
+ events: number;
196
+ /** Fraction of events where a look landed inside. The ceiling. */
197
+ lookRate: number;
198
+ /** Fraction of events the model was actually asked about. */
199
+ analyzeRate: number;
200
+ /** THE number: fraction of events that produced a correct fire. */
201
+ catchRate: number;
202
+ /**
203
+ * Fires with no event in progress, as a fraction of all fires. Reported
204
+ * BESIDE the catch rate and never folded into it: a detector that fires
205
+ * constantly has a perfect catch rate and is worthless.
206
+ */
207
+ falseTriggerRate: number;
208
+ /** Median seconds from event start to the analysis landing, for caught events. */
209
+ medianLatencyS: number | null;
210
+ /** Loss attribution — where the missed events went. */
211
+ lost: {
212
+ never_looked: number;
213
+ gate_dropped: number;
214
+ slot_starved: number;
215
+ buffer_expired: number;
216
+ model_wrong: number;
217
+ };
218
+ }
219
+ /**
220
+ * Group a replay into one row per shape.
221
+ *
222
+ * The false-trigger rate is charged to every shape that was present, because
223
+ * an idle analysis is not attributable to one shape — it happened when NOTHING
224
+ * was in progress. Reporting it per shape anyway is deliberate: an operator
225
+ * reads one row, and a row that hides the noise is the row that sells a
226
+ * detector nobody can live with.
227
+ */
228
+ export declare function reportByShape(result: ReplayResult): ShapeReport[];
229
+ /** Roll the shape rows up to the four reporting groups. */
230
+ export declare function reportByGroup(reports: readonly ShapeReport[]): Array<{
231
+ group: ShapeGroup;
232
+ events: number;
233
+ catchRate: number;
234
+ falseTriggerRate: number;
235
+ lookRate: number;
236
+ }>;
237
+ /**
238
+ * The look cadence a shape needs to reach `target`.
239
+ *
240
+ * `min(d/T,1) >= target => T <= d/target`. Reported so a red gate carries
241
+ * the fix rather than only the failure: a 2.2 s event at a 90% target needs a
242
+ * 2.44 s look cadence, which is a real, affordable number (looking costs
243
+ * 3.6 ms) and is 12x finer than the 30 s we ship.
244
+ */
245
+ export declare function requiredLookCadenceS(medianDurationS: number, target: number): number | null;
246
+ //# sourceMappingURL=sensingCatchRate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensingCatchRate.d.ts","sourceRoot":"","sources":["../src/sensingCatchRate.ts"],"names":[],"mappings":"AAqEA;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC;AAErE,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAAwD,CAAC;AAEvG;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,yEAAyE;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,UAAU,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,eAAe,GAAG,oBAAoB,CAAC;IAC3F;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAuElD,CAAC;AAIH,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAE1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,aAAa,CAAC,YAAY,CAAC,GACtC,aAAa,GAAG,IAAI,CAOtB;AAMD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMhG;AAMD,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,aAAa,CASlD,CAAC;AAEH,gCAAgC;AAChC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,MAAM,EAAE,OAAO,CAAC;IAChB,wEAAwE;IACxE,QAAQ,EAAE,OAAO,CAAC;IAClB,gEAAgE;IAChE,MAAM,EAAE,OAAO,CAAC;IAChB;;;;;;;;;;OAUG;IACH,MAAM,EAAE,cAAc,GAAG,cAAc,GAAG,cAAc,GAAG,gBAAgB,GAAG,aAAa,GAAG,IAAI,CAAC;IACnG,yEAAyE;IACzE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,0DAA0D;IAC1D,YAAY,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,aAAa,EAAE,MAAM,CAAC;IACtB,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;CACf;AAwBD;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CACpB,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,YAAK,EACnC,EAAE,SAAS,EAAE,IAAQ,EAAE,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D,YAAY,CAwKd;AAMD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,uDAAuD;IACvD,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CACzH;AAUD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,CA+BjE;AAED,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,KAAK,CAAC;IACpE,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;CAClG,CAAC,CAgBD;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3F"}