@trillboards/edge-sdk 0.2.19 → 0.2.20

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.
@@ -0,0 +1,369 @@
1
+ /**
2
+ * connectorUpdate — the CONSUMER the published version manifest never had.
3
+ *
4
+ * Every release publishes `trillboards-connector-<platform>.version.json` to the
5
+ * CDN with `connectorVersion`, `gitSha`, `sha256`, `sizeBytes` and `publishedAt`.
6
+ * Until this module existed, repo-wide the ONLY references to that object were
7
+ * the workflow that writes it, a test asserting the workflow writes it, and a
8
+ * README line. It was a producer with no consumer — the mirror image of the
9
+ * defect class in `docs/runbooks/telemetry-producer-substrate.md`, and just as
10
+ * invisible: the artifact that says "you are out of date" was published,
11
+ * correct, and read by nobody, so a field fix reached a customer only when that
12
+ * customer happened to re-download 2.6 GB and re-run the installer.
13
+ *
14
+ * THIS FILE ONLY CHECKS AND REPORTS. Applying an update is a separate,
15
+ * platform-specific transaction — see `deploy/windows/apply-update.ps1` and
16
+ * `connectorUpdateApply.ts`. The split is deliberate: "am I stale?" is a
17
+ * question every platform can answer over one 401-byte GET, while "swap the
18
+ * running binaries" is a Windows scheduled-task transaction with a rollback.
19
+ *
20
+ * ── WHY A 200 IS NOT AN ANSWER ──────────────────────────────────────────────
21
+ * The CDN in front of these objects serves the marketing SPA as its default
22
+ * behavior, so a MISSING manifest answers `HTTP 200 text/html`, not 404. Proved
23
+ * against production while writing this:
24
+ *
25
+ * $ curl -o /dev/null -w '%{http_code} %{content_type}\n' \
26
+ * .../connector/this-file-does-not-exist-control.json
27
+ * 200 text/html
28
+ *
29
+ * That is the exact shape of `.claude/lessons/2026-08-14-a-broken-probe-and-a-
30
+ * true-absence-are-the-same-bytes.md`. So the check is not "did the GET
31
+ * succeed"; it is "did the body parse as a manifest whose every required field
32
+ * is present and well-formed". A body that fails that test yields `null` —
33
+ * meaning UNKNOWN — and `null` is never rendered as "up to date". A staleness
34
+ * oracle that reports "current" when it cannot reach its own oracle is worse
35
+ * than no oracle at all.
36
+ *
37
+ * For the same reason `parseConnectorVersion` is STRICT rather than lenient.
38
+ * `edge-core`'s ModelManager parses versions with `.split('.').map(Number)` and
39
+ * `|| 0`, so a non-numeric version silently becomes `0.0.0` and every later
40
+ * comparison quietly answers "not newer" — forever, with no error anywhere. A
41
+ * version we cannot parse is a manifest we do not trust.
42
+ */
43
+ import { reportConnectorStatus } from './ConnectorStatusClient';
44
+ import type { ConnectorUpdateApplier } from './connectorUpdateApply';
45
+ /** Where the release workflows publish every platform's manifest. */
46
+ export declare const CONNECTOR_UPDATE_BASE_URL = "https://screen.trillboards.com/connector";
47
+ /**
48
+ * How often an install asks whether it is stale.
49
+ *
50
+ * Six hours. The GET is ~401 bytes, so the poll itself costs nothing, and the
51
+ * release workflow fires on every `production` push touching the edge
52
+ * workspaces (measured: 15 releases on 2026-08-13, 13 on 08-12), so a shorter
53
+ * period would only discover the same churn sooner. The FIRST check is deferred
54
+ * one whole interval, matching `ModelManager.start()` — a connector in a crash
55
+ * loop must not turn into a CDN hammer, and a machine that just installed is by
56
+ * definition current.
57
+ */
58
+ export declare const CONNECTOR_UPDATE_CHECK_INTERVAL_MS: number;
59
+ /**
60
+ * How old a release must be before an install will TAKE it.
61
+ *
62
+ * There is no canary ring in front of this. With ~13 releases a day reaching a
63
+ * fleet that auto-applies, a bad connector would be on every customer's PC
64
+ * within one check period, and the only recovery is another release. A bake
65
+ * window is the cheapest thing standing between "we merged a regression" and
66
+ * "every store stopped sensing", and it costs a fix at most one extra check.
67
+ *
68
+ * `publishedAt` comes from the manifest, i.e. from the same channel as the
69
+ * payload, so this is a release-hygiene control and NOT a security control. The
70
+ * security control is the Authenticode verification in the applier.
71
+ */
72
+ export declare const CONNECTOR_UPDATE_MIN_RELEASE_AGE_MS: number;
73
+ /**
74
+ * The published manifest, after strict validation.
75
+ *
76
+ * `updateUrl`/`updateCatalogUrl` are the code-only update payload and its
77
+ * Authenticode-signed hash catalog. They are OPTIONAL because a manifest
78
+ * published before the applier shipped carries neither, and an install that
79
+ * finds a newer version with no update payload must report the drift rather
80
+ * than fail — reporting is the half that works on every platform.
81
+ */
82
+ export interface ConnectorVersionManifest {
83
+ schemaVersion: number;
84
+ platform: string;
85
+ connectorVersion: string;
86
+ gitSha: string;
87
+ sha256: string;
88
+ sizeBytes: number;
89
+ publishedAt: string;
90
+ downloadUrl: string;
91
+ updateUrl?: string;
92
+ updateCatalogUrl?: string;
93
+ }
94
+ /** A parsed `MAJOR.MINOR.PATCH`. */
95
+ export interface ParsedConnectorVersion {
96
+ major: number;
97
+ minor: number;
98
+ patch: number;
99
+ }
100
+ /**
101
+ * Parse `MAJOR.MINOR.PATCH` (an optional leading `v`, an optional `-prerelease`
102
+ * or `+build` suffix that is IGNORED for ordering). Returns null — never a
103
+ * zeroed struct — for anything else.
104
+ */
105
+ export declare function parseConnectorVersion(raw: unknown): ParsedConnectorVersion | null;
106
+ /**
107
+ * Is `available` strictly newer than `installed`?
108
+ *
109
+ * FALSE whenever either side fails to parse. That direction is deliberate: an
110
+ * unparseable version must never authorise a swap of the running binaries. It
111
+ * also makes a DOWNGRADE impossible, which is the whole defence against a CDN
112
+ * that has been rolled back to an older (but still validly signed) payload.
113
+ */
114
+ export declare function isNewerConnectorVersion(available: unknown, installed: unknown): boolean;
115
+ /**
116
+ * The manifest object name for a platform, or null where no manifest is
117
+ * published. Linux has no packaged connector release and therefore no manifest;
118
+ * returning null keeps a Linux install from polling a URL that would answer 200
119
+ * with the marketing SPA on every check, forever.
120
+ */
121
+ export declare function manifestObjectForPlatform(platform: string): string | null;
122
+ /** Full manifest URL for a platform, or null. */
123
+ export declare function manifestUrlForPlatform(platform: string, baseUrl?: string): string | null;
124
+ /**
125
+ * Strictly validate a manifest body. Returns null when ANY required field is
126
+ * absent or malformed — including when the body is the CDN's HTML SPA fallback,
127
+ * which is what a deleted manifest looks like over the wire.
128
+ */
129
+ export declare function parseVersionManifest(body: string): ConnectorVersionManifest | null;
130
+ /** Injectable transport so tests never touch the network. */
131
+ export type ManifestFetcher = (url: string, timeoutMs: number) => Promise<{
132
+ statusCode: number;
133
+ body: string;
134
+ }>;
135
+ /**
136
+ * GET a small public object with a HARD byte cap.
137
+ *
138
+ * Deliberately not `AudienceAnalyzeClient`'s `defaultHttpPoster`: that one is a
139
+ * POST-shaped transport that concatenates every chunk with no ceiling, which is
140
+ * fine for an API we authenticate to and wrong for an unauthenticated public
141
+ * object whose expected size is 401 bytes. A response that keeps coming is
142
+ * destroyed rather than buffered.
143
+ *
144
+ * `Cache-Control: no-cache` + `Pragma: no-cache` are belt-and-braces. The object
145
+ * is published `no-cache, no-store, must-revalidate` precisely because it is the
146
+ * staleness oracle, but an intercepting corporate proxy is not obliged to
147
+ * honour a response header, and a cached manifest reports the PREVIOUS release
148
+ * as current for the whole TTL.
149
+ */
150
+ export declare const defaultManifestFetcher: ManifestFetcher;
151
+ /** Reads the published manifest for one platform. */
152
+ export declare class ConnectorManifestClient {
153
+ private readonly url;
154
+ private readonly timeoutMs;
155
+ private readonly fetcher;
156
+ constructor(options: {
157
+ platform: string;
158
+ baseUrl?: string;
159
+ timeoutMs?: number;
160
+ }, fetcher?: ManifestFetcher);
161
+ /** The resolved URL, or null on a platform that publishes no manifest. */
162
+ getEndpoint(): string | null;
163
+ /**
164
+ * The published manifest, or null for UNKNOWN — no platform manifest, a
165
+ * transport failure, a non-2xx, or a body that is not a valid manifest (the
166
+ * SPA-fallback case). Never throws; the caller keeps sensing either way.
167
+ */
168
+ fetchManifest(): Promise<ConnectorVersionManifest | null>;
169
+ }
170
+ /**
171
+ * What the connector is holding right now, as far as an update is concerned.
172
+ *
173
+ * Both numbers are read straight off `CloudSensingManager.getSensingHealth()`;
174
+ * nothing new is written or counted to support this.
175
+ */
176
+ export interface ConnectorBusyness {
177
+ /** Analyses the admission gate has admitted and not yet released. */
178
+ inFlight: number;
179
+ /** Flagged frames the candidate buffer is holding for a free slot. */
180
+ buffered: number;
181
+ }
182
+ /**
183
+ * Is this a moment at which the connector may be stopped and replaced?
184
+ *
185
+ * The two quantities are the connector's IRRECOVERABLE work:
186
+ *
187
+ * - `inFlight` — a frame the model is answering, or a POST in flight. There is
188
+ * no store-and-forward on the Windows connector (`SignalBuffer` is
189
+ * constructed only in `EdgeAgent`, which the Windows task never runs), so a
190
+ * kill here loses that observation permanently.
191
+ * - `buffered` — frames the motion cascade has ALREADY decided are
192
+ * interesting: a person entering a restricted area, a spill, a fall. At a
193
+ * 30 s scan cadence the next look is a different event. `CloudSensingManager
194
+ * .stop()` calls `candidates.reset()`, so these die on ANY stop, graceful or
195
+ * not — stopping while the buffer is loaded is the dropped-alert failure, and
196
+ * it is a product failure, not an implementation detail.
197
+ *
198
+ * NOT covered, and stated rather than hidden: a tick can be between
199
+ * `camera.getFrame()` and the admission gate — mid-decode, mid-motion-eval —
200
+ * with `inFlight === 0`, because on the cascade path the ticket is not taken
201
+ * until after the motion verdict. `LoopState.tickInFlight` is private and
202
+ * exposed nowhere. Losing that frame costs one SAMPLE that the cascade has not
203
+ * yet judged interesting, which is a different and much smaller loss than a
204
+ * flagged candidate, and the next tick captures a fresher frame. Widening the
205
+ * health struct to close it was judged not worth the blast radius.
206
+ */
207
+ export declare function isSafeToApplyUpdate(busyness: ConnectorBusyness): boolean;
208
+ /**
209
+ * Map a `getSensingHealth()` reading onto the two numbers that matter. Tolerant
210
+ * of a partial shape so a test fake or a future manager cannot crash the
211
+ * watcher; an absent field reads as 0, i.e. "not holding anything", which is
212
+ * only ever reached by a manager that has no buffer to hold anything in.
213
+ */
214
+ export declare function busynessOf(health: {
215
+ inFlight?: number;
216
+ candidateBuffer?: {
217
+ buffered?: number;
218
+ };
219
+ } | null | undefined): ConnectorBusyness;
220
+ /** Has this release sat long enough to be taken? */
221
+ export declare function isReleaseBakedEnough(manifest: ConnectorVersionManifest, nowMs: number, minAgeMs?: number): boolean;
222
+ /** What one check concluded. */
223
+ export interface ConnectorUpdateCheck {
224
+ installedVersion: string;
225
+ /** The published version, or null when the manifest could not be read. */
226
+ publishedVersion: string | null;
227
+ /** Published AND strictly newer than installed. Null when unknown. */
228
+ availableVersion: string | null;
229
+ /** The manifest itself, when it parsed. */
230
+ manifest: ConnectorVersionManifest | null;
231
+ }
232
+ /**
233
+ * One check: read the manifest, decide whether this install is behind.
234
+ *
235
+ * `availableVersion` is null both when the install is current AND when the
236
+ * manifest could not be read — but `publishedVersion` distinguishes them, so a
237
+ * caller that must not conflate "current" with "unknown" can.
238
+ */
239
+ export declare function checkForConnectorUpdate(installedVersion: string, client: ConnectorManifestClient): Promise<ConnectorUpdateCheck>;
240
+ /**
241
+ * Delay before the FIRST check.
242
+ *
243
+ * `ModelManager` defers its first check a whole hour, and that is right for a
244
+ * 2.4 GB model download. It is wrong here: this GET is 401 bytes, and deferring
245
+ * it six hours would mean a store PC that reboots nightly never reports its
246
+ * version at all — the fleet view would be blind to exactly the machines most
247
+ * likely to be stale. Sixty seconds is long enough for sensing to come up first
248
+ * and short enough that every start contributes a report.
249
+ *
250
+ * A fresh release still cannot be applied on that first check: the bake window
251
+ * is enforced separately, on `publishedAt`.
252
+ */
253
+ export declare const CONNECTOR_UPDATE_INITIAL_DELAY_MS = 60000;
254
+ /** How often the apply state machine looks at the world while an update is in flight. */
255
+ export declare const CONNECTOR_UPDATE_POLL_INTERVAL_MS = 60000;
256
+ /**
257
+ * How long to wait for staging to finish before giving up on this attempt.
258
+ *
259
+ * An hour. The payload is ~200 MB, and a store uplink is the slow case this
260
+ * number is for. Giving up is not a failure — the next check re-stages.
261
+ */
262
+ export declare const CONNECTOR_UPDATE_STAGE_DEADLINE_MS: number;
263
+ /**
264
+ * How long to wait for a safe point before applying anyway.
265
+ *
266
+ * Two hours, and the branch matters. On a saturated multi-camera install the
267
+ * candidate buffer may never reach zero — measured on a 24 h 32-camera
268
+ * simulation, 89,056 of 92,160 candidates were EVICTED, i.e. the buffer is
269
+ * permanently full and those frames are already being dropped by the buffer's
270
+ * own fairness bound. Waiting forever for a quiet moment on such a machine
271
+ * would mean it never receives another fix, which is the strictly worse
272
+ * outcome. So: take the first genuinely quiet moment; failing that, accept the
273
+ * loss after two hours and record which branch was taken.
274
+ */
275
+ export declare const CONNECTOR_UPDATE_SAFE_POINT_DEADLINE_MS: number;
276
+ /** Handle returned by the service, mirroring `GemmaModelOtaHandle`. */
277
+ export interface ConnectorUpdateWatcherHandle {
278
+ stop(): void;
279
+ }
280
+ export interface ConnectorUpdateServiceDeps {
281
+ /** This install's version (`require('../package.json').version`). */
282
+ installedVersion: string;
283
+ /** `process.platform` in production; injected in tests. */
284
+ platform: string;
285
+ /** Where to report the version. */
286
+ apiBaseUrl: string;
287
+ /** One token per paired feed; each binds to its own screen. */
288
+ deviceTokens: string[];
289
+ /**
290
+ * The connector's current irrecoverable-work reading. Omit to CHECK and
291
+ * REPORT without ever applying — which is what every platform but Windows
292
+ * does, and what a caller with no manager to ask should do.
293
+ */
294
+ busyness?: () => ConnectorBusyness;
295
+ /**
296
+ * Stop sensing cleanly and end the process, handing the machine to the
297
+ * applier. Defaults to a bare `process.exit(0)`; the CLI entrypoints pass
298
+ * their existing shutdown closure so cameras are closed first.
299
+ */
300
+ requestExit?: () => void;
301
+ /** Windows applier. Omit (or pass null) to check and report only. */
302
+ applier?: ConnectorUpdateApplier | null;
303
+ log?: (message: string) => void;
304
+ client?: ConnectorManifestClient;
305
+ intervalMs?: number;
306
+ initialDelayMs?: number;
307
+ pollIntervalMs?: number;
308
+ stageDeadlineMs?: number;
309
+ safePointDeadlineMs?: number;
310
+ minReleaseAgeMs?: number;
311
+ now?: () => number;
312
+ reportStatus?: typeof reportConnectorStatus;
313
+ setTimeoutFn?: typeof setTimeout;
314
+ clearTimeoutFn?: typeof clearTimeout;
315
+ setIntervalFn?: typeof setInterval;
316
+ clearIntervalFn?: typeof clearInterval;
317
+ }
318
+ /**
319
+ * The whole update loop: check the manifest, tell the server where this install
320
+ * stands, and — on Windows, with a verified payload and a quiet moment — apply.
321
+ *
322
+ * Every branch is best-effort. A failed check, a failed report, an applier that
323
+ * will not launch: each is one log line, and sensing continues. The one thing
324
+ * this must never do is stop the connector for any reason other than a
325
+ * deliberate, verified handoff.
326
+ */
327
+ export declare function startConnectorUpdateService(deps: ConnectorUpdateServiceDeps): ConnectorUpdateWatcherHandle | null;
328
+ /**
329
+ * Every device token this install holds, de-duplicated.
330
+ *
331
+ * One token per feed, because a token binds to exactly one screen — so a
332
+ * 16-camera store reports 16 times and every screen's row carries the version
333
+ * of the one connector serving it. Structurally typed rather than importing
334
+ * `EdgeAgentConfig` so this stays testable without a config file on disk.
335
+ */
336
+ export declare function connectorDeviceTokens(config: {
337
+ deviceToken?: string;
338
+ cameras?: Array<{
339
+ deviceToken?: string;
340
+ }> | null;
341
+ }): string[];
342
+ /**
343
+ * The one call every long-running sensing entrypoint makes.
344
+ *
345
+ * Deliberately NOT wired inside `buildCloudSensingManager`/
346
+ * `buildLocalSensingManager`: `auto-sense` builds BOTH managers and caches them,
347
+ * so a watcher created per manager would give that mode two update loops racing
348
+ * each other into the same swap. It belongs to the PROCESS, so it is started
349
+ * once per entrypoint.
350
+ *
351
+ * `combinedSense` (`sense`) is deliberately absent: the Windows task's
352
+ * `ValidateSet` admits only auto-sense/local-sense/cloud-sense, so that mode
353
+ * never runs on the platform this applies to.
354
+ */
355
+ export declare function startConnectorUpdates(opts: {
356
+ config: {
357
+ apiBaseUrl?: string;
358
+ deviceToken?: string;
359
+ cameras?: Array<{
360
+ deviceToken?: string;
361
+ }> | null;
362
+ };
363
+ installedVersion: string;
364
+ busyness?: () => ConnectorBusyness;
365
+ requestExit?: () => void;
366
+ log?: (msg: string) => void;
367
+ platform?: string;
368
+ }): ConnectorUpdateWatcherHandle | null;
369
+ //# sourceMappingURL=connectorUpdate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connectorUpdate.d.ts","sourceRoot":"","sources":["../src/connectorUpdate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAIH,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAErE,qEAAqE;AACrE,eAAO,MAAM,yBAAyB,6CAA6C,CAAC;AAEpF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kCAAkC,QAAqB,CAAC;AAErE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mCAAmC,QAAqB,CAAC;AAQtE;;;;;;;;GAQG;AACH,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,oCAAoC;AACpC,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,sBAAsB,GAAG,IAAI,CAKjF;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,CAOvF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIzE;AAED,iDAAiD;AACjD,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAkC,GAC1C,MAAM,GAAG,IAAI,CAIf;AAMD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,wBAAwB,GAAG,IAAI,CAoClF;AAED,6DAA6D;AAC7D,MAAM,MAAM,eAAe,GAAG,CAC5B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,KACd,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,sBAAsB,EAAE,eA4CjC,CAAC;AAEL,qDAAqD;AACrD,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;gBAGxC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,EACnE,OAAO,CAAC,EAAE,eAAe;IAO3B,0EAA0E;IAC1E,WAAW,IAAI,MAAM,GAAG,IAAI;IAI5B;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC;CAWhE;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,GACxF,iBAAiB,CAOnB;AAED,oDAAoD;AACpD,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,wBAAwB,EAClC,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,MAA4C,GACrD,OAAO,CAMT;AAED,gCAAgC;AAChC,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,0EAA0E;IAC1E,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,sEAAsE;IACtE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,2CAA2C;IAC3C,QAAQ,EAAE,wBAAwB,GAAG,IAAI,CAAC;CAC3C;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,oBAAoB,CAAC,CAY/B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iCAAiC,QAAS,CAAC;AAExD,yFAAyF;AACzF,eAAO,MAAM,iCAAiC,QAAS,CAAC;AAExD;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,QAAiB,CAAC;AAEjE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,uCAAuC,QAAqB,CAAC;AAE1E,uEAAuE;AACvE,MAAM,WAAW,4BAA4B;IAC3C,IAAI,IAAI,IAAI,CAAC;CACd;AAED,MAAM,WAAW,0BAA0B;IACzC,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,iBAAiB,CAAC;IACnC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,qEAAqE;IACrE,OAAO,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACxC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,qBAAqB,CAAC;IAC5C,YAAY,CAAC,EAAE,OAAO,UAAU,CAAC;IACjC,cAAc,CAAC,EAAE,OAAO,YAAY,CAAC;IACrC,aAAa,CAAC,EAAE,OAAO,WAAW,CAAC;IACnC,eAAe,CAAC,EAAE,OAAO,aAAa,CAAC;CACxC;AAID;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,0BAA0B,GAC/B,4BAA4B,GAAG,IAAI,CAsMrC;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;CAClD,GAAG,MAAM,EAAE,CAOX;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE;QACN,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,KAAK,CAAC;YAAE,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,GAAG,IAAI,CAAC;KAClD,CAAC;IACF,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,iBAAiB,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,4BAA4B,GAAG,IAAI,CAmCtC"}