openlimiter 0.1.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.
package/dist/render.js ADDED
@@ -0,0 +1,357 @@
1
+ import { collectionIdentity, failureSentence, floorFixed, freshness } from "@openlimiter/core";
2
+ export function pressureOf(percent) {
3
+ if (!Number.isFinite(percent))
4
+ return "none";
5
+ if (percent >= 90)
6
+ return "critical";
7
+ if (percent >= 80)
8
+ return "urgent";
9
+ if (percent >= 60)
10
+ return "watch";
11
+ return "healthy";
12
+ }
13
+ /** How many of the ten blocks a percentage lights, never rounding upward. */
14
+ export const BAR_SEGMENTS = 10;
15
+ /**
16
+ * The statusline's own density.
17
+ *
18
+ * Five blocks, not ten. A statusline shares one row with a model name, a
19
+ * branch, a directory and whatever else the host puts there, and six ten block
20
+ * bars would take the row on their own. Half the blocks at twice the price per
21
+ * block reads at a glance and still lands every reading in the right band,
22
+ * which is all a status row is for. The snapshot table keeps all ten, because
23
+ * a table is read deliberately and has the room.
24
+ */
25
+ export const STATUSLINE_BAR_SEGMENTS = 5;
26
+ export function filledSegments(percent, segments = BAR_SEGMENTS) {
27
+ if (!Number.isFinite(percent))
28
+ return 0;
29
+ if (!Number.isInteger(segments) || segments < 1)
30
+ return 0;
31
+ const bounded = Math.min(100, Math.max(0, percent));
32
+ return Math.min(segments, Math.floor(bounded / (100 / segments)));
33
+ }
34
+ /* ------------------------------------------------------------------ colour */
35
+ const ESCAPE = "\u001b[";
36
+ const RESET = ESCAPE + "0m";
37
+ /**
38
+ * The eight colour codes every terminal has had since the 1970s.
39
+ *
40
+ * There is no orange among them, which is the whole difficulty with a four band
41
+ * scale: the band between yellow and red has no colour of its own to be drawn
42
+ * in on a plain terminal.
43
+ */
44
+ const BAND_CODE = {
45
+ healthy: "32",
46
+ watch: "33",
47
+ urgent: "33",
48
+ critical: "31",
49
+ none: "90"
50
+ };
51
+ /**
52
+ * Orange, from the 256 colour cube, for the terminals that have one.
53
+ *
54
+ * `38;5;208` selects entry 208 of the extended palette, which is the orange
55
+ * sitting between the yellow at 80 and the red at 90 rather than beside either.
56
+ */
57
+ const ORANGE_256 = "38;5;208";
58
+ /** The one red every failure line is painted in. */
59
+ const RED = "31";
60
+ /**
61
+ * Whether this run may emit escape codes.
62
+ *
63
+ * Two things veto colour, and either one is enough: the NO_COLOR convention,
64
+ * which any value at all switches on, and standard output not being a
65
+ * terminal, which is what a pipe into a file or another program looks like.
66
+ */
67
+ export function supportsColor(environment, isTty) {
68
+ if (environment["NO_COLOR"] !== undefined)
69
+ return false;
70
+ return isTty;
71
+ }
72
+ /**
73
+ * Whether this terminal has more than the eight standard colours.
74
+ *
75
+ * Two signals, either one enough. A `TERM` naming `256color` is the convention
76
+ * terminfo has used for decades, and a `COLORTERM` set to anything at all is
77
+ * what the terminals that went further than 256 announce themselves with. Both
78
+ * are claims the terminal makes about itself, not measurements, so this answers
79
+ * a question about what may safely be emitted and never about what is true.
80
+ *
81
+ * A terminal that says neither is not an error and is not a lesser rendering.
82
+ * It gets the yellow of the band below, so the reading still reads as pressure
83
+ * and only the distinction between 80 and 60 is lost. Information degrades; it
84
+ * never breaks, and no escape code is ever emitted that a terminal would print
85
+ * as literal characters.
86
+ */
87
+ export function supports256Color(environment) {
88
+ const term = environment["TERM"];
89
+ if (term !== undefined && term.includes("256color"))
90
+ return true;
91
+ return environment["COLORTERM"] !== undefined;
92
+ }
93
+ /**
94
+ * Whether this terminal can draw the eighth block glyphs used for sub character
95
+ * bar resolution.
96
+ *
97
+ * Three things veto it, and any one is enough: the NO_COLOR convention, a
98
+ * stream that is not a terminal, and a platform whose default console draws box
99
+ * characters as empty rectangles. A fallback to plain ASCII blocks keeps the
100
+ * output readable on the platforms that need it.
101
+ */
102
+ export function supportsEighthBlocks(environment, isTty, platform) {
103
+ if (environment["NO_COLOR"] !== undefined)
104
+ return false;
105
+ if (!isTty)
106
+ return false;
107
+ if (platform === "win32" && environment["WT_SESSION"] === undefined)
108
+ return false;
109
+ return true;
110
+ }
111
+ /**
112
+ * The one place a band becomes a colour.
113
+ *
114
+ * Both the ten block table bar and the five block statusline bar come through
115
+ * here, so a reading is the same colour wherever it is drawn, and the orange
116
+ * fallback is decided once rather than at each call site.
117
+ */
118
+ export function bandCode(band, wide) {
119
+ if (band === "urgent" && wide)
120
+ return ORANGE_256;
121
+ return BAND_CODE[band];
122
+ }
123
+ function paint(text, code, color) {
124
+ return color ? ESCAPE + code + "m" + text + RESET : text;
125
+ }
126
+ /** The eighth block glyphs, from one eighth to seven eighths. */
127
+ const EIGHTH_GLYPHS = ["", "\u258f", "\u258e", "\u258d", "\u258c", "\u258b", "\u258a", "\u2589"];
128
+ /**
129
+ * The segmented bar.
130
+ *
131
+ * Ten blocks by default, the same ten the dashboard and the desktop window
132
+ * draw, and five when the statusline asks for its own density. With colour it
133
+ * is drawn in block characters and painted in the band's colour. Without colour
134
+ * it is the same positions in plain ASCII, because a terminal that reported no
135
+ * colour support may also be a log file, and a log file should carry no escape
136
+ * codes at all.
137
+ *
138
+ * The table bar also gains sub character resolution when the terminal can draw
139
+ * the eighth block glyphs, so readings that differ by a few percent no longer
140
+ * share the same bar. A terminal that cannot draw them falls back to the whole
141
+ * block rendering, exactly as before.
142
+ *
143
+ * The block count is the only thing the caller chooses. The band, and therefore
144
+ * the colour, comes from the reading alone, so the same percentage is the same
145
+ * colour at either density.
146
+ *
147
+ * `wide` is the terminal's own claim about its palette, and it defaults to the
148
+ * answer read off the environment so every caller gets the right one without
149
+ * carrying it. A test passes it explicitly, because a test that asks the
150
+ * machine it happens to be running on what colours it has is not a test.
151
+ */
152
+ export function meterBar(percent, state, color, segments = BAR_SEGMENTS, wide = supports256Color(process.env), eighthBlocks = supportsEighthBlocks(process.env, process.stdout.isTTY === true, process.platform)) {
153
+ const known = state !== "unknown";
154
+ const band = known ? pressureOf(percent) : "none";
155
+ if (segments === BAR_SEGMENTS && known && eighthBlocks) {
156
+ const bounded = Math.min(100, Math.max(0, percent));
157
+ const totalEighths = Math.round((bounded / 100) * segments * 8);
158
+ const full = Math.floor(totalEighths / 8);
159
+ const remainder = totalEighths % 8;
160
+ const empty = Math.max(0, segments - full - (remainder > 0 ? 1 : 0));
161
+ const glyphs = "\u2588".repeat(full) +
162
+ (remainder > 0 ? EIGHTH_GLYPHS[remainder] : "") +
163
+ "\u2591".repeat(empty);
164
+ return paint(glyphs, bandCode(band, wide), color);
165
+ }
166
+ const filled = known ? filledSegments(percent, segments) : 0;
167
+ const empty = Math.max(0, segments - filled);
168
+ const glyphs = color
169
+ ? "\u2588".repeat(filled) + "\u2591".repeat(empty)
170
+ : "#".repeat(filled) + ".".repeat(empty);
171
+ return paint(glyphs, bandCode(band, wide), color);
172
+ }
173
+ /** A failure, in red, in our own fixed words. */
174
+ export function failureLine(provider, category, color) {
175
+ return paint(provider + " " + category + " " + failureSentence[category], RED, color);
176
+ }
177
+ export function failureLines(failures, color) {
178
+ return failures.map((failure) => failureLine(failure.provider, failure.category, color));
179
+ }
180
+ /* ------------------------------------------------------------------ fields */
181
+ const MINUTE = 60_000;
182
+ const HOUR = 3_600_000;
183
+ const DAY = 86_400_000;
184
+ /**
185
+ * Time left before the window resets, compact enough for a table column.
186
+ *
187
+ * Two units at most and no spaces, so every row stays one space separated
188
+ * record that a script can still split. A window with no reset says so rather
189
+ * than printing a zero.
190
+ */
191
+ export function timeToReset(resetAt, now) {
192
+ if (resetAt === null)
193
+ return "NONE";
194
+ const target = Date.parse(resetAt);
195
+ const current = Date.parse(now);
196
+ if (!Number.isFinite(target) || !Number.isFinite(current))
197
+ return "NONE";
198
+ const remaining = target - current;
199
+ if (remaining <= 0)
200
+ return "PASSED";
201
+ if (remaining < MINUTE)
202
+ return "<1m";
203
+ if (remaining < HOUR)
204
+ return String(Math.floor(remaining / MINUTE)) + "m";
205
+ if (remaining < DAY) {
206
+ return String(Math.floor(remaining / HOUR)) + "h" +
207
+ String(Math.floor((remaining % HOUR) / MINUTE)) + "m";
208
+ }
209
+ return String(Math.floor(remaining / DAY)) + "d" +
210
+ String(Math.floor((remaining % DAY) / HOUR)) + "h";
211
+ }
212
+ /**
213
+ * Money, when the reading carries it.
214
+ *
215
+ * The three fields travel together out of the normalizer, so checking one is
216
+ * enough, and the currency is a closed literal rather than provider text.
217
+ */
218
+ export function amountField(snapshot) {
219
+ const used = snapshot.usedAmount;
220
+ const limit = snapshot.limitAmount;
221
+ if (used === undefined || limit === undefined || snapshot.currency === undefined) {
222
+ return "NONE";
223
+ }
224
+ return "$" + floorFixed(used, 2) + "/$" + floorFixed(limit, 2);
225
+ }
226
+ /* ------------------------------------------------------------------- table */
227
+ /** The column order and the header labels that sit above them. */
228
+ const COLUMNS = [
229
+ { key: "provider", header: "PROVIDER" },
230
+ { key: "meter", header: "METER" },
231
+ { key: "bar", header: "BAR" },
232
+ { key: "usage", header: "USAGE" },
233
+ { key: "amount", header: "AMOUNT" },
234
+ { key: "state", header: "STATE" },
235
+ { key: "reset", header: "RESET" },
236
+ { key: "remaining", header: "IN" },
237
+ { key: "chip", header: "SOURCE" }
238
+ ];
239
+ export const TABLE_HEADER = COLUMNS.map((column) => column.header).join(" ");
240
+ /** How wide the provider identity may grow before it is truncated. */
241
+ const MAX_PROVIDER_WIDTH = 13;
242
+ /** The one ellipsis, kept as a single character so truncation costs one cell. */
243
+ const ELLIPSIS = "\u2026";
244
+ /** The provider identity, with its account when one is present. */
245
+ function providerIdentity(snapshot) {
246
+ return collectionIdentity(snapshot.provider, snapshot.accountId);
247
+ }
248
+ /** Trim an identity to the column width, keeping the leftmost characters. */
249
+ function truncateIdentity(text, maxWidth) {
250
+ if (text.length <= maxWidth)
251
+ return text;
252
+ return text.slice(0, Math.max(0, maxWidth - 1)) + ELLIPSIS;
253
+ }
254
+ /**
255
+ * Map a snapshot's provenance to a connection state based source chip.
256
+ *
257
+ * The vocabulary is the one in packages/core/src/connection-state.ts, because
258
+ * a parser is not a connection and only the product's own lifecycle words may
259
+ * describe where a reading came from.
260
+ */
261
+ function provenanceConnectionState(provenance) {
262
+ if (provenance === undefined)
263
+ return "NOT_CONFIGURED";
264
+ if (provenance.sourceKind === "statusline_payload")
265
+ return "CONNECTED";
266
+ if (provenance.sourceKind === "explicit_ingest")
267
+ return "IMPORT_ONLY";
268
+ if (provenance.sourceKind === "manual_document")
269
+ return "MANUAL";
270
+ if (provenance.sourceKind === "remote_api")
271
+ return "CONNECTED";
272
+ return "ERROR";
273
+ }
274
+ /** One short bracket chip describing the snapshot's source. */
275
+ function provenanceChip(provenance) {
276
+ if (provenance?.sourceKind === "statusline_payload" &&
277
+ provenance.observedVia === "claude_code_statusline") {
278
+ return "[local cli]";
279
+ }
280
+ const state = provenanceConnectionState(provenance);
281
+ const label = state === "IMPORT_ONLY"
282
+ ? "import only"
283
+ : state.replace(/_/gu, " ").toLowerCase();
284
+ return "[" + label + "]";
285
+ }
286
+ function buildRow(snapshot, now, color) {
287
+ const state = freshness(snapshot.observedAt, snapshot.expiresAt, now);
288
+ return {
289
+ provider: truncateIdentity(providerIdentity(snapshot), MAX_PROVIDER_WIDTH),
290
+ meter: snapshot.meter,
291
+ bar: meterBar(snapshot.value, state, color),
292
+ usage: floorFixed(snapshot.value, 2) + snapshot.unit,
293
+ amount: amountField(snapshot),
294
+ state,
295
+ reset: snapshot.resetAt ?? "NONE",
296
+ remaining: timeToReset(snapshot.resetAt, now),
297
+ chip: provenanceChip(snapshot.provenance)
298
+ };
299
+ }
300
+ /** The visible width of a field, which differs from its string length for bars. */
301
+ function visibleWidth(key, value) {
302
+ if (key === "bar")
303
+ return BAR_SEGMENTS;
304
+ return value.length;
305
+ }
306
+ /** Render rows with every column padded to its widest value so lines align. */
307
+ function renderRows(rows) {
308
+ const widths = {};
309
+ for (const column of COLUMNS) {
310
+ widths[column.key] = Math.max(column.header.length, ...rows.map((row) => visibleWidth(column.key, row[column.key])));
311
+ }
312
+ const header = COLUMNS
313
+ .map((column) => column.header.padEnd(widths[column.key]))
314
+ .join(" ");
315
+ const lines = [header];
316
+ for (const row of rows) {
317
+ lines.push(COLUMNS
318
+ .map((column) => row[column.key].padEnd(widths[column.key]))
319
+ .join(" "));
320
+ }
321
+ return lines.join("\n");
322
+ }
323
+ /**
324
+ * Sort providers by their most constrained meter, then keep each provider's
325
+ * rows together so a person reads one account at a time.
326
+ */
327
+ function orderSnapshots(snapshots) {
328
+ const grouped = new Map();
329
+ for (const snapshot of snapshots) {
330
+ const group = grouped.get(snapshot.provider) ?? [];
331
+ group.push(snapshot);
332
+ grouped.set(snapshot.provider, group);
333
+ }
334
+ const ordered = [...grouped.entries()].sort((left, right) => {
335
+ const leftMax = Math.max(...left[1].map((snapshot) => snapshot.value));
336
+ const rightMax = Math.max(...right[1].map((snapshot) => snapshot.value));
337
+ if (rightMax !== leftMax)
338
+ return rightMax - leftMax;
339
+ return left[0].localeCompare(right[0]);
340
+ });
341
+ const result = [];
342
+ for (const [, group] of ordered) {
343
+ result.push(...[...group].sort((left, right) => {
344
+ if (right.value !== left.value)
345
+ return right.value - left.value;
346
+ return left.meter.localeCompare(right.meter);
347
+ }));
348
+ }
349
+ return result;
350
+ }
351
+ export function renderTable(snapshots, now, color) {
352
+ if (snapshots.length === 0)
353
+ return "No bounded quota data is available.";
354
+ const rows = orderSnapshots(snapshots).map((snapshot) => buildRow(snapshot, now, color));
355
+ return renderRows(rows);
356
+ }
357
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
package/dist/serve.d.ts CHANGED
@@ -16,8 +16,12 @@ import { type Advice } from "@openlimiter/core";
16
16
  * Four gates stand between the socket and that payload:
17
17
  *
18
18
  * 1. A random token is generated on every start and is required on every
19
- * route. It lives only in memory, is never written to disk, and is void
20
- * the moment the command stops.
19
+ * route that carries data. It lives only in memory, is never written to
20
+ * disk, and is void the moment the command stops. The empty page shell at
21
+ * the root is the one route served without it, because the token travels
22
+ * in the URL fragment and a fragment never reaches a server. The shell
23
+ * holds no quota state, no token and no account detail: it is markup that
24
+ * then has to authenticate before anything is filled in.
21
25
  * 2. The Host header must be an address literal or localhost, which is what
22
26
  * closes a DNS rebinding attack from a page on an attacker's domain.
23
27
  * 3. Cross origin requests are refused outright. The page this server hands
@@ -36,8 +40,29 @@ export declare const DEFAULT_SERVE_PORT = 7317;
36
40
  export declare const DEFAULT_SERVE_HOST = "0.0.0.0";
37
41
  /** Payload schema version. Bumped only on a breaking shape change. */
38
42
  export declare const SERVE_SCHEMA = 1;
39
- /** Query parameter carrying the token. Short, because it goes in a QR symbol. */
43
+ /**
44
+ * Name the token travels under. Short, because it goes in a QR symbol.
45
+ *
46
+ * It is the key in the URL FRAGMENT of every address this command prints, and
47
+ * for one more release it is also accepted as a query parameter so an address
48
+ * saved from an older build keeps working.
49
+ */
40
50
  export declare const TOKEN_PARAMETER = "t";
51
+ /**
52
+ * Why the token is in the fragment rather than the query.
53
+ *
54
+ * A query string is part of the request line. It lands in the phone's browser
55
+ * history, in the omnibox suggestions, in whatever cloud that browser syncs
56
+ * history to, and in the Referer of any link the page might carry. A fragment
57
+ * is never sent to a server at all: it stays in the address bar until the page
58
+ * itself reads it, and the page's first act is to move it into sessionStorage
59
+ * and rewrite the address to a clean one. From that point the token exists only
60
+ * in the tab's own memory and is sent as an Authorization header, so no URL
61
+ * anywhere on the phone carries the capability.
62
+ *
63
+ * docs/SYNC_ARCHITECTURE.md already required exactly this of pairing links.
64
+ */
65
+ export declare const TOKEN_FRAGMENT_PREFIX: string;
41
66
  /**
42
67
  * One provider line, carrying exactly the fields the agent context carries.
43
68
  *
@@ -94,6 +119,14 @@ export declare function lanAddress(): string | null;
94
119
  * cannot be rebound.
95
120
  */
96
121
  export declare function isAllowedHostHeader(header: string | undefined, boundPort: number): boolean;
122
+ /**
123
+ * Read the token a request presents.
124
+ *
125
+ * The header is the supported way and is read first. The query parameter is a
126
+ * fallback kept for one release so an address copied out of an older build
127
+ * still answers; nothing this command prints uses it any more.
128
+ */
129
+ export declare function presentedToken(authorization: string | undefined, target: URL): string | null;
97
130
  /**
98
131
  * Build the document served on the quota route.
99
132
  *
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AASA,OAAO,EAML,KAAK,MAAM,EACZ,MAAM,mBAAmB,CAAC;AAG3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,oEAAoE;AACpE,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,mFAAmF;AACnF,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAE5C,sEAAsE;AACtE,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,iFAAiF;AACjF,eAAO,MAAM,eAAe,MAAM,CAAC;AAcnC;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,YAAY,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzB,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAO1C;AAOD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,SAAS,EAAE,MAAM,GAChB,OAAO,CAkBT;AAaD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,aAAa,CAAC,CAmBxB;AAsDD;;;;;;;GAOG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAsHnC;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAgH5B;AAED,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wCAAwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CA6BR"}
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AASA,OAAO,EAML,KAAK,MAAM,EACZ,MAAM,mBAAmB,CAAC;AAG3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,oEAAoE;AACpE,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,mFAAmF;AACnF,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAE5C,sEAAsE;AACtE,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,QAA8B,CAAC;AAiBjE;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,YAAY,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzB,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAO1C;AAOD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,SAAS,EAAE,MAAM,GAChB,OAAO,CAkBT;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,MAAM,EAAE,GAAG,GACV,MAAM,GAAG,IAAI,CAUf;AAaD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,aAAa,CAAC,CAmBxB;AAsDD;;;;;;;GAOG;AACH,wBAAgB,UAAU,IAAI,MAAM,CA4JnC;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAwH5B;AAED,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wCAAwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CAiCR"}