@knpkv/herdr-usage 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +11 -2
- package/dist/app.d.ts +18 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +77 -0
- package/dist/app.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +24 -0
- package/dist/bin.js.map +1 -0
- package/dist/client/client.css +2 -0
- package/dist/client/client.css.map +7 -0
- package/dist/client/client.js +180 -0
- package/dist/client/client.js.map +7 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +88 -0
- package/dist/client.js.map +1 -0
- package/dist/host/failure.d.ts +15 -0
- package/dist/host/failure.d.ts.map +1 -0
- package/dist/host/failure.js +44 -0
- package/dist/host/failure.js.map +1 -0
- package/dist/host/limits.d.ts +59 -0
- package/dist/host/limits.d.ts.map +1 -0
- package/dist/host/limits.js +96 -0
- package/dist/host/limits.js.map +1 -0
- package/dist/host/usage.d.ts +93 -0
- package/dist/host/usage.d.ts.map +1 -0
- package/dist/host/usage.js +95 -0
- package/dist/host/usage.js.map +1 -0
- package/dist/host.d.ts +12 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +12 -0
- package/dist/host.js.map +1 -0
- package/dist/options.d.ts +24 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +28 -0
- package/dist/options.js.map +1 -0
- package/dist/selection.d.ts +8 -0
- package/dist/selection.d.ts.map +1 -0
- package/dist/selection.js +8 -0
- package/dist/selection.js.map +1 -0
- package/dist/views/usage-empty-art.d.ts +4 -0
- package/dist/views/usage-empty-art.d.ts.map +1 -0
- package/dist/views/usage-empty-art.js +8 -0
- package/dist/views/usage-empty-art.js.map +1 -0
- package/dist/views/usage-limits-chart-view.d.ts +12 -0
- package/dist/views/usage-limits-chart-view.d.ts.map +1 -0
- package/dist/views/usage-limits-chart-view.js +8 -0
- package/dist/views/usage-limits-chart-view.js.map +1 -0
- package/dist/views/usage-limits-chart.d.ts +28 -0
- package/dist/views/usage-limits-chart.d.ts.map +1 -0
- package/dist/views/usage-limits-chart.js +50 -0
- package/dist/views/usage-limits-chart.js.map +1 -0
- package/dist/views/usage-limits-page.d.ts +61 -0
- package/dist/views/usage-limits-page.d.ts.map +1 -0
- package/dist/views/usage-limits-page.js +275 -0
- package/dist/views/usage-limits-page.js.map +1 -0
- package/dist/views/usage-limits-view.d.ts +20 -0
- package/dist/views/usage-limits-view.d.ts.map +1 -0
- package/dist/views/usage-limits-view.js +36 -0
- package/dist/views/usage-limits-view.js.map +1 -0
- package/dist/views/usage-page.d.ts +53 -0
- package/dist/views/usage-page.d.ts.map +1 -0
- package/dist/views/usage-page.js +242 -0
- package/dist/views/usage-page.js.map +1 -0
- package/dist/views/usage-selection.d.ts +24 -0
- package/dist/views/usage-selection.d.ts.map +1 -0
- package/dist/views/usage-selection.js +51 -0
- package/dist/views/usage-selection.js.map +1 -0
- package/dist/views/views.css +1034 -0
- package/dist/views.d.ts +13 -0
- package/dist/views.d.ts.map +1 -0
- package/dist/views.js +13 -0
- package/dist/views.js.map +1 -0
- package/package.json +90 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FleetLimits, FleetUsage, Received } from "@knpkv/herdr-connect/usage";
|
|
2
|
+
import * as AsyncResult from "effect/reactivity/AsyncResult";
|
|
3
|
+
import type { ReactElement } from "react";
|
|
4
|
+
/**
|
|
5
|
+
* The Limits page body the 06 Usage design draws for the hub's own read: notices, the verdict, one card per tool.
|
|
6
|
+
* Loading and a first failed read keep the reference's skeleton and retry line; a failed refresh keeps the last
|
|
7
|
+
* reading and says so. `now` is this page's clock, compared only with when the page received the read.
|
|
8
|
+
*/
|
|
9
|
+
export declare const UsageLimitsReadings: ({ host, limits, now, onRetry, overview, timeZone, usage }: {
|
|
10
|
+
readonly host: string;
|
|
11
|
+
readonly limits: AsyncResult.AsyncResult<Received<FleetLimits>, unknown>;
|
|
12
|
+
readonly now: number;
|
|
13
|
+
readonly onRetry: () => void;
|
|
14
|
+
/** The Tokens page, where the chart's "Fleet token overview" leads. */
|
|
15
|
+
readonly overview: string;
|
|
16
|
+
readonly timeZone: string;
|
|
17
|
+
/** The last usage read, for the hub's token chart; null until one arrives. */
|
|
18
|
+
readonly usage: FleetUsage | null;
|
|
19
|
+
}) => ReactElement;
|
|
20
|
+
//# sourceMappingURL=usage-limits-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-limits-view.d.ts","sourceRoot":"","sources":["../../src/views/usage-limits-view.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAGnF,OAAO,KAAK,WAAW,MAAM,+BAA+B,CAAA;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AA0CzC;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,8DAQ7B;IACD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAA;IACxE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;CAClC,KAAG,YA4EH,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, LimitTrack, Notice, Skeleton, StateLabel } from "@knpkv/rly/primitives";
|
|
3
|
+
import { Option } from "effect";
|
|
4
|
+
import * as AsyncResult from "effect/reactivity/AsyncResult";
|
|
5
|
+
import { limitsChart } from "./usage-limits-chart.js";
|
|
6
|
+
import { UsageLimitsChart } from "./usage-limits-chart-view.js";
|
|
7
|
+
import { limitsPage } from "./usage-limits-page.js";
|
|
8
|
+
const Card = ({ card }) => (_jsxs("section", { className: "usage-limits-card", "aria-label": `${card.name} limits`, "data-tool": card.agent, children: [_jsxs("div", { className: "usage-limits-card-head", children: [_jsx("h2", { children: card.name }), _jsx("small", { children: card.read })] }), _jsxs("div", { className: "usage-limits-figure", children: [_jsx("b", { "data-unknown": card.figure === null ? "true" : undefined, children: card.figure === null ? "Unknown" : `${String(card.figure)}%` }), _jsx("span", { children: card.measures })] }), card.state === null ? null : (_jsx("span", { children: _jsx(StateLabel, { label: card.state.label, tone: card.state.tone, size: "compact" }) })), card.track === null ? null : (_jsxs("div", { children: [_jsxs("span", { className: "usage-limits-sr", children: [card.track.label, ": ", card.track.valueText] }), _jsx(LimitTrack, { value: card.track.value, stale: card.track.stale })] })), _jsx("dl", { children: card.details.map(([term, value]) => (_jsxs("div", { children: [_jsx("dt", { children: term }), _jsx("dd", { "data-unknown": value === null ? "true" : undefined, children: value ?? "Unknown" })] }, term))) }), card.note === null ? null : _jsx("p", { className: "usage-limits-note", children: card.note })] }));
|
|
9
|
+
/**
|
|
10
|
+
* The Limits page body the 06 Usage design draws for the hub's own read: notices, the verdict, one card per tool.
|
|
11
|
+
* Loading and a first failed read keep the reference's skeleton and retry line; a failed refresh keeps the last
|
|
12
|
+
* reading and says so. `now` is this page's clock, compared only with when the page received the read.
|
|
13
|
+
*/
|
|
14
|
+
export const UsageLimitsReadings = ({ host, limits, now, onRetry, overview, timeZone, usage }) => {
|
|
15
|
+
const last = Option.getOrNull(AsyncResult.value(limits));
|
|
16
|
+
const failed = AsyncResult.isFailure(limits);
|
|
17
|
+
if (last === null && failed) {
|
|
18
|
+
return (_jsxs("div", { className: "usage-limits-unavailable", children: [_jsx("div", { className: "usage-limits-controls", children: _jsx(Button, { variant: "secondary", size: "dense", "data-region": "action", onClick: onRetry, children: "Retry" }) }), _jsx("p", { className: "usage-limits-retry", role: "status", "data-region": "notice", children: "Couldn't load limits. Trying again every minute." })] }));
|
|
19
|
+
}
|
|
20
|
+
if (last === null) {
|
|
21
|
+
return (_jsxs("div", { className: "usage-limits-loading", "aria-label": "Loading limits", "aria-busy": "true", "data-region": "cards", children: [_jsx(Skeleton, { variant: "text", style: { inlineSize: "9rem" } }), _jsx(Skeleton, { variant: "block", style: { blockSize: "76px" } }), _jsx(Skeleton, { variant: "block", style: { blockSize: "76px" } }), _jsx(Skeleton, { variant: "block", style: { blockSize: "76px" } })] }));
|
|
22
|
+
}
|
|
23
|
+
const page = limitsPage(last.fleet, host, now - last.receivedAt, timeZone);
|
|
24
|
+
// A tool whose limits cannot be read is left out of every token total: Unknown is not zero.
|
|
25
|
+
const chart = page === null || usage === null
|
|
26
|
+
? null
|
|
27
|
+
: limitsChart(usage, host, page.cards.filter((card) => card.figure === null).map((card) => card.agent));
|
|
28
|
+
const notices = [
|
|
29
|
+
...(failed
|
|
30
|
+
? [{ title: "Couldn't refresh limits.", text: "This is the previous reading. Trying again every minute." }]
|
|
31
|
+
: []),
|
|
32
|
+
...(page?.notices ?? [])
|
|
33
|
+
];
|
|
34
|
+
return (_jsxs(_Fragment, { children: [notices.length === 0 ? null : (_jsx("div", { className: "usage-limits-notices", "data-region": "notice", children: notices.map((notice) => (_jsx(Notice, { tone: "caution", children: _jsxs("span", { children: [_jsx("b", { children: notice.title }), " ", notice.text] }) }, notice.title))) })), page === null ? (_jsxs("p", { className: "usage-limits-retry", role: "status", children: ["No limits reading from ", host, " yet."] })) : (_jsxs(_Fragment, { children: [_jsxs("section", { className: "usage-limits-summary", "aria-label": "Room to work", "data-region": "summary", children: [_jsx("h2", { children: page.summary.verdict }), _jsx("p", { children: page.summary.note })] }), _jsx("div", { className: "usage-limits-cards", "data-region": "cards", children: page.cards.map((card) => (_jsx(Card, { card: card }, card.agent))) }), chart === null ? null : _jsx(UsageLimitsChart, { chart: chart, overview: overview })] }))] }));
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=usage-limits-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-limits-view.js","sourceRoot":"","sources":["../../src/views/usage-limits-view.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type FleetLimits, type FleetReadLoadError, type FleetUsage, type Received, type UsageQuery } from "@knpkv/herdr-connect/usage";
|
|
2
|
+
import { Effect, Schema } from "effect";
|
|
3
|
+
import { type ReactElement, type ReactNode } from "react";
|
|
4
|
+
export declare const UsagePageId: Schema.Literals<readonly ["limits", "tokens", "by-tool"]>;
|
|
5
|
+
export type UsagePageId = typeof UsagePageId.Type;
|
|
6
|
+
/** The Usage pages, in navigation order. The hub's core descriptor and the app's manifest both list these. */
|
|
7
|
+
export declare const usagePages: ReadonlyArray<{
|
|
8
|
+
readonly id: UsagePageId;
|
|
9
|
+
readonly label: string;
|
|
10
|
+
}>;
|
|
11
|
+
/**
|
|
12
|
+
* The header chrome a shell lends the Usage page: the Limits page groups its title and tabs into `headerOutlet`
|
|
13
|
+
* (`setGrouped`), and with nothing recorded anywhere asks for the empty-state chrome (`setEmpty`). Null when the
|
|
14
|
+
* shell has none, as standalone.
|
|
15
|
+
*/
|
|
16
|
+
export interface UsageChrome {
|
|
17
|
+
readonly host: string;
|
|
18
|
+
readonly headerOutlet: HTMLElement | null;
|
|
19
|
+
readonly setEmpty: (empty: boolean) => void;
|
|
20
|
+
readonly setGrouped: (grouped: boolean) => void;
|
|
21
|
+
}
|
|
22
|
+
/** What the page needs from whichever shell renders it: the hub's module mount, or the app's own client. */
|
|
23
|
+
export interface UsageShell {
|
|
24
|
+
/** False while the page is hidden; reads stop. */
|
|
25
|
+
readonly active: boolean;
|
|
26
|
+
/** Replace the current location; selectors change in place. */
|
|
27
|
+
readonly navigate: (href: string) => void;
|
|
28
|
+
/** The link to one Usage page with these selectors. */
|
|
29
|
+
readonly href: (page: UsagePageId, search: URLSearchParams) => string;
|
|
30
|
+
readonly chrome: UsageChrome | null;
|
|
31
|
+
/** The by-tool host picker's trailing glyph, in the shell's own icon set. */
|
|
32
|
+
readonly nextIcon: ReactNode;
|
|
33
|
+
}
|
|
34
|
+
export interface UsageModuleReads {
|
|
35
|
+
readonly usage: (query: UsageQuery) => Effect.Effect<Received<FleetUsage>, FleetReadLoadError>;
|
|
36
|
+
readonly limits: Effect.Effect<Received<FleetLimits>, FleetReadLoadError>;
|
|
37
|
+
}
|
|
38
|
+
export interface UsageModuleContent {
|
|
39
|
+
/** The hub's own host: the Limits page shows its account limits only. */
|
|
40
|
+
readonly host: string;
|
|
41
|
+
readonly reads: UsageModuleReads;
|
|
42
|
+
readonly viewerTimeZone: string;
|
|
43
|
+
readonly now: number;
|
|
44
|
+
readonly onHubMachine: boolean;
|
|
45
|
+
}
|
|
46
|
+
/** One Usage page. Readings persist across pages while the shell keeps the page root mounted. */
|
|
47
|
+
export declare const UsagePage: ({ content, page, search, shell }: {
|
|
48
|
+
readonly content: UsageModuleContent;
|
|
49
|
+
readonly shell: UsageShell;
|
|
50
|
+
readonly page: UsagePageId;
|
|
51
|
+
readonly search: URLSearchParams;
|
|
52
|
+
}) => ReactElement;
|
|
53
|
+
//# sourceMappingURL=usage-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-page.d.ts","sourceRoot":"","sources":["../../src/views/usage-page.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EAEf,KAAK,QAAQ,EAIb,KAAK,UAAU,EAChB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,MAAM,EAAmC,MAAM,EAAE,MAAM,QAAQ,CAAA;AAExE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAuC,MAAM,OAAO,CAAA;AAM9F,eAAO,MAAM,WAAW,2DAAmD,CAAA;AAC3E,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAEjD,8GAA8G;AAC9G,eAAO,MAAM,UAAU,EAAE,aAAa,CAAC;IACrC,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAIA,CAAA;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,YAAY,EAAE,WAAW,GAAG,IAAI,CAAA;IACzC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3C,QAAQ,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CAChD;AAED,4GAA4G;AAC5G,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,KAAK,MAAM,CAAA;IACrE,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;IACnC,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC,CAAA;IAC9F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC,CAAA;CAC1E;AAED,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAA;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;CAC/B;AAiFD,iGAAiG;AACjG,eAAO,MAAM,SAAS,qCAKnB;IACD,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;CACjC,KAAG,YAkeH,CAAA"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { AGENT_USAGE_PAGE, limitsState, UsageTab, usageState } from "@knpkv/herdr-connect/usage";
|
|
3
|
+
import { Button, StateLabel, ToggleGroup } from "@knpkv/rly/primitives";
|
|
4
|
+
import { Effect, Fiber, Option, Result, Schedule, Schema } from "effect";
|
|
5
|
+
import * as AsyncResult from "effect/reactivity/AsyncResult";
|
|
6
|
+
import { useEffect, useId, useMemo, useState } from "react";
|
|
7
|
+
import { createPortal } from "react-dom";
|
|
8
|
+
import { UsageEmptyArt } from "./usage-empty-art.js";
|
|
9
|
+
import { UsageLimitsReadings } from "./usage-limits-view.js";
|
|
10
|
+
import { canonicalUsageSelection } from "./usage-selection.js";
|
|
11
|
+
export const UsagePageId = Schema.Literals(["limits", "tokens", "by-tool"]);
|
|
12
|
+
/** The Usage pages, in navigation order. The hub's core descriptor and the app's manifest both list these. */
|
|
13
|
+
export const usagePages = [
|
|
14
|
+
{ id: "limits", label: "Limits" },
|
|
15
|
+
{ id: "tokens", label: "Tokens" },
|
|
16
|
+
{ id: "by-tool", label: "By tool" }
|
|
17
|
+
];
|
|
18
|
+
const usagePollInterval = "5 minutes";
|
|
19
|
+
/** Serial cached reads stop when the module is inactive or hidden, including an in-flight request. */
|
|
20
|
+
const useUsageRead = (read, enabled, interval, refresh) => {
|
|
21
|
+
const [result, setResult] = useState(AsyncResult.initial());
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!enabled)
|
|
24
|
+
return;
|
|
25
|
+
let current = true;
|
|
26
|
+
const pass = Effect.gen(function* () {
|
|
27
|
+
yield* Effect.sync(() => setResult((previous) => AsyncResult.waiting(previous)));
|
|
28
|
+
const exit = yield* Effect.exit(read);
|
|
29
|
+
if (!current)
|
|
30
|
+
return;
|
|
31
|
+
yield* Effect.sync(() => setResult((previous) => AsyncResult.fromExitWithPrevious(exit, Option.some(previous))));
|
|
32
|
+
}).pipe(Effect.repeat(Schedule.spaced(interval)));
|
|
33
|
+
const fiber = Effect.runFork(pass);
|
|
34
|
+
return () => {
|
|
35
|
+
current = false;
|
|
36
|
+
Effect.runFork(Fiber.interrupt(fiber));
|
|
37
|
+
};
|
|
38
|
+
}, [read, enabled, interval, refresh]);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
const filterHosts = (fleet, host) => host === null
|
|
42
|
+
? fleet
|
|
43
|
+
: {
|
|
44
|
+
...fleet,
|
|
45
|
+
hosts: fleet.hosts.filter((entry) => entry.host.toLowerCase() === host.toLowerCase()),
|
|
46
|
+
failures: fleet.failures.filter((entry) => entry.host.toLowerCase() === host.toLowerCase())
|
|
47
|
+
};
|
|
48
|
+
/** Only complete matching host reads can establish that neither tokens nor limits have been recorded. */
|
|
49
|
+
const emptyFleetReadings = (usage, limits) => {
|
|
50
|
+
if (!usage.peersListed || !limits.peersListed || usage.failures.length > 0 || limits.failures.length > 0)
|
|
51
|
+
return false;
|
|
52
|
+
const usageHosts = new Set(usage.hosts.map(({ host }) => host.toLowerCase()));
|
|
53
|
+
const limitHosts = new Set(limits.hosts.map(({ host }) => host.toLowerCase()));
|
|
54
|
+
return (usageHosts.size > 0 &&
|
|
55
|
+
usageHosts.size === usage.hosts.length &&
|
|
56
|
+
limitHosts.size === limits.hosts.length &&
|
|
57
|
+
usageHosts.size === limitHosts.size &&
|
|
58
|
+
[...usageHosts].every((host) => limitHosts.has(host)) &&
|
|
59
|
+
usage.hosts.every(({ reading }) => reading._tag === "Read" &&
|
|
60
|
+
reading.skipped === 0 &&
|
|
61
|
+
reading.usage.tokens.length === 0 &&
|
|
62
|
+
reading.usage.limits.length === 0) &&
|
|
63
|
+
limits.hosts.every(({ reading }) => reading._tag === "Read" && reading.skipped === 0 && reading.limits.latest.length === 0));
|
|
64
|
+
};
|
|
65
|
+
const rangeLabels = { "24h": "24 hours", "7d": "7 days", "30d": "30 days" };
|
|
66
|
+
const toolLabels = { claude: "Claude Code", codex: "Codex" };
|
|
67
|
+
const compact = new Intl.NumberFormat("en", { notation: "compact", maximumFractionDigits: 1 });
|
|
68
|
+
const failureWords = {
|
|
69
|
+
offline: "Offline",
|
|
70
|
+
unavailable: "No tailnet address",
|
|
71
|
+
timeout: "No answer",
|
|
72
|
+
request_failed: "Request failed",
|
|
73
|
+
invalid_response: "Unexpected answer"
|
|
74
|
+
};
|
|
75
|
+
/** One Usage page. Readings persist across pages while the shell keeps the page root mounted. */
|
|
76
|
+
export const UsagePage = ({ content, page, search, shell }) => {
|
|
77
|
+
const headingId = useId();
|
|
78
|
+
const hostId = useId();
|
|
79
|
+
const [visible, setVisible] = useState(() => document.visibilityState === "visible");
|
|
80
|
+
const [repaired, setRepaired] = useState(false);
|
|
81
|
+
const [refresh, setRefresh] = useState(0);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
const changed = () => setVisible(document.visibilityState === "visible");
|
|
84
|
+
document.addEventListener("visibilitychange", changed);
|
|
85
|
+
return () => document.removeEventListener("visibilitychange", changed);
|
|
86
|
+
}, []);
|
|
87
|
+
const query = search.toString();
|
|
88
|
+
const decoded = useMemo(() => canonicalUsageSelection(new URLSearchParams(query), content.viewerTimeZone), [query, content.viewerTimeZone]);
|
|
89
|
+
const selection = Result.isSuccess(decoded) ? decoded.success.selection : null;
|
|
90
|
+
const range = selection?.range ?? "7d";
|
|
91
|
+
const timeZone = selection?.timeZone ?? content.viewerTimeZone;
|
|
92
|
+
const read = useMemo(() => content.reads.usage({ range, timeZone }), [content.reads.usage, range, timeZone]);
|
|
93
|
+
const enabled = shell.active && visible && selection !== null;
|
|
94
|
+
const usage = useUsageRead(read, enabled, usagePollInterval, refresh);
|
|
95
|
+
const limits = useUsageRead(content.reads.limits, enabled && page === "limits", "1 minute", refresh);
|
|
96
|
+
const usageReading = Option.getOrNull(AsyncResult.value(usage));
|
|
97
|
+
const limitsReading = Option.getOrNull(AsyncResult.value(limits));
|
|
98
|
+
const emptyChrome = shell.chrome;
|
|
99
|
+
const empty = page === "limits" &&
|
|
100
|
+
AsyncResult.isSuccess(usage) &&
|
|
101
|
+
AsyncResult.isSuccess(limits) &&
|
|
102
|
+
emptyFleetReadings(usage.value.fleet, limits.value.fleet);
|
|
103
|
+
const setEmpty = emptyChrome?.setEmpty;
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
setEmpty?.(shell.active && empty);
|
|
106
|
+
return () => setEmpty?.(false);
|
|
107
|
+
}, [empty, shell.active, setEmpty]);
|
|
108
|
+
const setGrouped = emptyChrome?.setGrouped;
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
setGrouped?.(shell.active && page === "limits");
|
|
111
|
+
return () => setGrouped?.(false);
|
|
112
|
+
}, [shell.active, page, setGrouped]);
|
|
113
|
+
const knownHosts = [
|
|
114
|
+
...new Set([
|
|
115
|
+
...(usageReading?.fleet.hosts.map((entry) => entry.host) ?? []),
|
|
116
|
+
...(usageReading?.fleet.failures.map((entry) => entry.host) ?? []),
|
|
117
|
+
...(page === "limits" ? (limitsReading?.fleet.hosts.map((entry) => entry.host) ?? []) : []),
|
|
118
|
+
...(page === "limits" ? (limitsReading?.fleet.failures.map((entry) => entry.host) ?? []) : [])
|
|
119
|
+
])
|
|
120
|
+
].sort((a, b) => a.localeCompare(b));
|
|
121
|
+
const hostsComplete = AsyncResult.isSuccess(usage) &&
|
|
122
|
+
usage.value.fleet.peersListed &&
|
|
123
|
+
(page !== "limits" || (AsyncResult.isSuccess(limits) && limits.value.fleet.peersListed));
|
|
124
|
+
const unknownHost = selection?.host !== null &&
|
|
125
|
+
selection?.host !== undefined &&
|
|
126
|
+
hostsComplete &&
|
|
127
|
+
!knownHosts.some((host) => host.toLowerCase() === selection.host?.toLowerCase());
|
|
128
|
+
const selectedHost = unknownHost ? null : (selection?.host ?? null);
|
|
129
|
+
useEffect(() => {
|
|
130
|
+
if (!shell.active || Result.isFailure(decoded))
|
|
131
|
+
return;
|
|
132
|
+
const canonical = new URLSearchParams(decoded.success.search);
|
|
133
|
+
if (unknownHost)
|
|
134
|
+
canonical.delete("host");
|
|
135
|
+
if (canonical.toString() === query)
|
|
136
|
+
return;
|
|
137
|
+
if (decoded.success.repaired || unknownHost)
|
|
138
|
+
setRepaired(true);
|
|
139
|
+
shell.navigate(shell.href(page, canonical));
|
|
140
|
+
}, [decoded, unknownHost, query, page, shell]);
|
|
141
|
+
if (Result.isFailure(decoded))
|
|
142
|
+
return (_jsxs("section", { className: "usage-details", "data-usage-page": page, children: [_jsx("h1", { children: "Usage unavailable" }), _jsx("p", { children: "The browser's time zone could not be read." })] }));
|
|
143
|
+
const changeSelection = (next) => {
|
|
144
|
+
setRepaired(false);
|
|
145
|
+
const query = new URLSearchParams({ range: next.range, timeZone: next.timeZone });
|
|
146
|
+
if (next.host !== null)
|
|
147
|
+
query.set("host", next.host);
|
|
148
|
+
shell.navigate(shell.href(page, query));
|
|
149
|
+
};
|
|
150
|
+
const filteredUsage = AsyncResult.map(usage, (received) => ({
|
|
151
|
+
...received,
|
|
152
|
+
fleet: filterHosts(received.fleet, selectedHost)
|
|
153
|
+
}));
|
|
154
|
+
const filteredLimits = AsyncResult.map(limits, (received) => ({
|
|
155
|
+
...received,
|
|
156
|
+
fleet: filterHosts(received.fleet, selectedHost)
|
|
157
|
+
}));
|
|
158
|
+
const shown = Option.getOrNull(AsyncResult.value(filteredUsage));
|
|
159
|
+
const hostTotals = shown?.fleet.hosts.map((host) => ({
|
|
160
|
+
host: host.host,
|
|
161
|
+
reading: host.reading,
|
|
162
|
+
total: host.reading._tag === "Read" ? host.reading.usage.tokens.reduce((sum, cell) => sum + cell.tokens, 0) : null
|
|
163
|
+
})) ?? [];
|
|
164
|
+
const counted = hostTotals.filter((host) => host.total !== null);
|
|
165
|
+
const total = counted.reduce((sum, host) => sum + (host.total ?? 0), 0);
|
|
166
|
+
const breakdownHost = selectedHost ?? counted[0]?.host ?? null;
|
|
167
|
+
const providerTotals = new Map();
|
|
168
|
+
const modelTotals = new Map();
|
|
169
|
+
for (const host of hostTotals) {
|
|
170
|
+
if (host.reading._tag !== "Read" || host.host.toLowerCase() !== breakdownHost?.toLowerCase())
|
|
171
|
+
continue;
|
|
172
|
+
for (const cell of host.reading.usage.tokens) {
|
|
173
|
+
providerTotals.set(cell.agent, (providerTotals.get(cell.agent) ?? 0) + cell.tokens);
|
|
174
|
+
const label = `${toolLabels[cell.agent]}, ${cell.model}`;
|
|
175
|
+
modelTotals.set(label, (modelTotals.get(label) ?? 0) + cell.tokens);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const shownRange = counted.find((host) => host.reading._tag === "Read")?.reading;
|
|
179
|
+
const summary = counted.length === 0
|
|
180
|
+
? "No token reading is available yet."
|
|
181
|
+
: `${compact.format(total)} reported tokens in the last ${shownRange?._tag === "Read" ? rangeLabels[shownRange.usage.range.preset] : rangeLabels[range]} from ${counted.length} ${counted.length === 1 ? "host" : "hosts"}.`;
|
|
182
|
+
// Loading and a first failed read show only their own state, as the reference draws them.
|
|
183
|
+
const limitsShown = Option.isSome(AsyncResult.value(limits));
|
|
184
|
+
const tabProps = {
|
|
185
|
+
presentation: { page: "tokens", labelledBy: headingId },
|
|
186
|
+
onHubMachine: false,
|
|
187
|
+
range,
|
|
188
|
+
onRangeChange: (range) => changeSelection({ ...decoded.success.selection, range }),
|
|
189
|
+
usage: usageState(filteredUsage, content.now),
|
|
190
|
+
limits: limitsState(filteredLimits, content.now)
|
|
191
|
+
};
|
|
192
|
+
/** The Usage page tabs; the shell's grouped header and the module page style them by class. */
|
|
193
|
+
const pageTabs = (className) => (_jsx("nav", { "aria-label": "Usage pages", className: className, "data-region": "tabs", children: usagePages.map((entry) => (_jsx("a", { href: shell.href(entry.id, new URLSearchParams(decoded.success.search)), "aria-current": page === entry.id ? "page" : undefined, "data-module-page": entry.id, children: entry.label }, entry.id))) }));
|
|
194
|
+
const toolReading = hostTotals.find((host) => host.host.toLowerCase() === breakdownHost?.toLowerCase())?.reading;
|
|
195
|
+
const toolFailure = shown?.fleet.failures.find((entry) => entry.host.toLowerCase() === breakdownHost?.toLowerCase());
|
|
196
|
+
const toolTotal = toolReading?._tag === "Read" ? [...providerTotals.values()].reduce((sum, tokens) => sum + tokens, 0) : null;
|
|
197
|
+
if (empty && emptyChrome !== null) {
|
|
198
|
+
const mast = (_jsxs("div", { className: "usage-empty-mast", children: [_jsxs("div", { className: "usage-empty-titles", children: [_jsx("div", { className: "usage-empty-title", "aria-hidden": "true", children: "Usage" }), _jsxs("p", { children: ["Usage details on ", emptyChrome.host, ". Account readings stay on this machine."] })] }), pageTabs("usage-empty-tabs")] }));
|
|
199
|
+
return (_jsxs("div", { className: "usage-limits-empty", "data-usage-page": "limits", "data-usage-empty": "true", "aria-label": "Usage Limits", children: [_jsx("h1", { id: headingId, className: "usage-page-heading", children: "Usage" }), emptyChrome.headerOutlet === null ? mast : createPortal(mast, emptyChrome.headerOutlet), _jsxs("section", { className: "usage-empty-notice", "data-region": "notice", children: [_jsx(UsageEmptyArt, {}), _jsx("h2", { children: "No usage readings yet" }), _jsxs("p", { children: [emptyChrome.host, " hasn\u2019t recorded any limits or token use. Unknown is not zero."] }), _jsx("a", { href: shell.href("tokens", new URLSearchParams(decoded.success.search)), className: "usage-empty-action", "data-region": "action", children: "See fleet token readings" })] })] }));
|
|
200
|
+
}
|
|
201
|
+
const detailsMast = (_jsxs("div", { className: "usage-details-mast", children: [_jsxs("header", { className: "usage-details-intro", children: [_jsx("h1", { id: headingId, children: "Usage" }), _jsx("p", { children: "Limits and tokens, per host, tool and model" }), repaired ? _jsx("p", { children: "Some URL selectors were reset. Valid selections were kept." }) : null] }), pageTabs("usage-details-tabs")] }));
|
|
202
|
+
// Limits groups its title and tabs with the shell header (the design's header region). The empty slot keeps the
|
|
203
|
+
// grid gap that followed the mast, so the controls stay where they were.
|
|
204
|
+
const mastOutlet = page === "limits" ? (emptyChrome?.headerOutlet ?? null) : null;
|
|
205
|
+
return (_jsxs("div", { className: "usage-details", "data-usage-page": page, children: [mastOutlet === null ? (detailsMast) : (_jsxs(_Fragment, { children: [_jsx("h1", { id: headingId, className: "usage-page-heading", children: "Usage" }), _jsx("div", { className: "usage-details-mast-slot" }), createPortal(_jsxs("div", { className: "usage-empty-mast", children: [_jsxs("div", { className: "usage-empty-titles", children: [_jsx("div", { className: "usage-empty-title", "aria-hidden": "true", children: "Usage" }), _jsx("p", { children: "Limits and tokens, per host, tool and model" }), repaired ? _jsx("p", { children: "Some URL selectors were reset. Valid selections were kept." }) : null] }), pageTabs("usage-empty-tabs")] }), mastOutlet)] })), page === "limits" ? null : (_jsxs("div", { className: "usage-details-controls", children: [_jsxs("label", { htmlFor: hostId, children: ["Host", _jsxs("select", { id: hostId, name: "usage-host", value: page === "by-tool" ? (breakdownHost ?? "") : (selectedHost ?? ""), onChange: (event) => changeSelection({ ...decoded.success.selection, host: event.currentTarget.value || null }), children: [page === "by-tool" ? (breakdownHost === null ? (_jsx("option", { value: "", children: "No reported host" })) : null) : (_jsx("option", { value: "", children: "All hosts" })), knownHosts.map((host) => (_jsx("option", { value: host, children: host }, host))), selectedHost !== null && !knownHosts.includes(selectedHost) ? (_jsx("option", { value: selectedHost, children: selectedHost })) : null] }), page === "by-tool" ? shell.nextIcon : null] }), _jsx(ToggleGroup, { "aria-label": "Range", value: range, items: Object.entries(rangeLabels).map(([value, label]) => ({ value, label })), onValueChange: (value) => {
|
|
206
|
+
const next = value === "24h" || value === "7d" || value === "30d" ? value : null;
|
|
207
|
+
if (next !== null)
|
|
208
|
+
changeSelection({ ...decoded.success.selection, range: next });
|
|
209
|
+
} }), _jsxs("span", { className: "usage-details-time-zone", children: ["Periods in ", timeZone] }), content.onHubMachine ? (_jsx("a", { href: AGENT_USAGE_PAGE, target: "_blank", rel: "noreferrer", children: "Open agent-usage on this machine" })) : null, AsyncResult.isFailure(usage) && (page !== "by-tool" || toolReading?._tag !== "Read") ? (_jsx(Button, { onClick: () => setRefresh((previous) => previous + 1), children: "Retry" })) : null] })), page === "by-tool" &&
|
|
210
|
+
toolReading?._tag === "Read" &&
|
|
211
|
+
usage.waiting &&
|
|
212
|
+
toolReading.usage.range.preset !== range ? (_jsx(StateLabel, { className: "usage-by-tool-updating", role: "status", tone: "neutral", icon: "loader", size: "compact", label: `Updating to ${rangeLabels[range]}… showing the last ${rangeLabels[toolReading.usage.range.preset]}` })) : null, page === "by-tool" && toolReading?._tag === "Read" && AsyncResult.isFailure(usage) ? (_jsxs("div", { className: "usage-by-tool-notice", role: "status", children: [_jsxs("div", { children: [_jsx(StateLabel, { label: "Couldn\u2019t refresh", tone: "caution", icon: "alert", size: "compact" }), toolReading?._tag !== "Read" ? null : (_jsxs("span", { children: ["Previous reading", " ", _jsx("time", { dateTime: new Date(toolReading.usage.observedAt).toISOString(), children: new Date(toolReading.usage.observedAt).toLocaleTimeString("en-GB", {
|
|
213
|
+
hour: "2-digit",
|
|
214
|
+
minute: "2-digit",
|
|
215
|
+
timeZone
|
|
216
|
+
}) }), ". Retrying every ", usagePollInterval, "."] }))] }), _jsx(Button, { variant: "secondary", size: "dense", onClick: () => setRefresh((previous) => previous + 1), children: "Retry" })] })) : null, page === "by-tool" ? (_jsxs("section", { className: "usage-details-section usage-by-tool", "aria-label": "By tool", children: [_jsx("h2", { className: "usage-by-tool-heading", children: "By tool" }), _jsxs("div", { className: "usage-by-tool-reading", children: [_jsx("strong", { className: "usage-by-tool-total", children: toolTotal === null ? "Unknown" : `${compact.format(toolTotal)} tokens` }), _jsx("p", { children: toolReading?._tag === "Read" ? (_jsxs(_Fragment, { children: [breakdownHost, ", last ", rangeLabels[toolReading.usage.range.preset], ", read", " ", _jsx("time", { dateTime: new Date(toolReading.usage.observedAt).toISOString(), children: new Date(toolReading.usage.observedAt).toLocaleTimeString("en-GB", {
|
|
217
|
+
hour: "2-digit",
|
|
218
|
+
minute: "2-digit",
|
|
219
|
+
timeZone
|
|
220
|
+
}) })] })) : toolReading !== undefined ? (toolReading.detail) : toolFailure !== undefined ? (`${toolFailure.host}: ${failureWords[toolFailure.reason]}`) : ("No tool reading is available yet.") })] }), _jsxs("table", { "aria-label": breakdownHost === null ? "By tool and model" : `By tool and model on ${breakdownHost}`, children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", children: "Tool and model" }), _jsx("th", { scope: "col", children: "Tokens" }), _jsx("th", { scope: "col", children: "Share" }), _jsx("th", { scope: "col", children: "Share track" })] }) }), _jsx("tbody", { children: [...modelTotals]
|
|
221
|
+
.sort(([, left], [, right]) => right - left)
|
|
222
|
+
.map(([label, tokens]) => (_jsxs("tr", { children: [_jsx("th", { scope: "row", children: label }), _jsx("td", { children: compact.format(tokens) }), _jsx("td", { children: toolTotal === null || toolTotal === 0
|
|
223
|
+
? "0%"
|
|
224
|
+
: `${String(Math.round((tokens / toolTotal) * 100))}%` }), _jsx("td", { className: "usage-by-tool-track", children: _jsx("progress", { "aria-hidden": "true", max: 100, value: toolTotal === null || toolTotal === 0 ? 0 : (tokens / toolTotal) * 100 }) })] }, label))) })] }), _jsx("p", { children: "Per tool and model on one host at a time; splits are never summed across hosts. Moved here from Fleet / Usage." }), shown === null ||
|
|
225
|
+
(shown.fleet.peersListed &&
|
|
226
|
+
shown.fleet.failures.length === 0 &&
|
|
227
|
+
counted.length === hostTotals.length) ? null : (_jsx("p", { children: "Unknown hosts are left out of totals. No token reading is treated as zero." }))] })) : page === "limits" ? (_jsx(_Fragment, { children: _jsx(UsageLimitsReadings, { host: content.host, limits: limits, now: content.now, onRetry: () => setRefresh((previous) => previous + 1), overview: shell.href("tokens", new URLSearchParams(decoded.success.search)), timeZone: timeZone, usage: usageReading?.fleet ?? null }) })) : (_jsx(UsageTab, { ...tabProps })), page === "tokens" ? (_jsxs(_Fragment, { children: [_jsxs("section", { className: "usage-details-section", "aria-label": "By host", children: [_jsx("h2", { children: "By host" }), _jsx("p", { children: summary }), _jsxs("ul", { children: [hostTotals.map((host) => (_jsxs("li", { children: [_jsxs("span", { children: [_jsx("strong", { children: host.host }), host.reading._tag === "Read" ? (_jsxs("time", { dateTime: new Date(host.reading.usage.observedAt).toISOString(), children: ["Read", " ", new Date(host.reading.usage.observedAt).toLocaleTimeString("en-GB", {
|
|
228
|
+
hour: "2-digit",
|
|
229
|
+
minute: "2-digit",
|
|
230
|
+
timeZone
|
|
231
|
+
}), " ", "in ", timeZone] })) : (_jsx("small", { children: host.reading.detail }))] }), _jsx("strong", { children: host.total === null ? "Unknown" : compact.format(host.total) })] }, host.host))), shown?.fleet.failures.map((failure) => (_jsxs("li", { children: [_jsxs("span", { children: [_jsx("strong", { children: failure.host }), _jsx("small", { children: failureWords[failure.reason] })] }), _jsx("strong", { children: "Unknown" })] }, failure.host)))] }), shown !== null &&
|
|
232
|
+
(!shown.fleet.peersListed || shown.fleet.failures.length > 0 || counted.length < hostTotals.length) ? (_jsx("p", { children: "Unknown hosts are left out of the total." })) : null] }), _jsxs("section", { className: "usage-details-section", "aria-label": "By provider", children: [_jsx("h2", { children: "By provider" }), _jsx("p", { children: breakdownHost === null
|
|
233
|
+
? "No provider reading is available yet."
|
|
234
|
+
: `On ${breakdownHost}. Splits stay on this host.` }), _jsx("ul", { children: [...providerTotals]
|
|
235
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
236
|
+
.map(([label, total]) => (_jsxs("li", { children: [_jsx("span", { children: label }), _jsx("strong", { children: compact.format(total) })] }, label))) })] }), _jsxs("section", { className: "usage-details-section", "aria-label": "By agent and model", children: [_jsx("h2", { children: "By agent and model" }), _jsx("p", { children: breakdownHost === null
|
|
237
|
+
? "No agent and model reading is available yet."
|
|
238
|
+
: `On ${breakdownHost}. Tokens cannot be attributed to individual bots.` }), _jsx("ul", { children: [...modelTotals]
|
|
239
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
240
|
+
.map(([label, total]) => (_jsxs("li", { children: [_jsx("span", { children: label }), _jsx("strong", { children: compact.format(total) })] }, label))) })] })] })) : null, page !== "limits" ? (_jsx("footer", { className: "usage-details-footer", children: _jsx("p", { children: "Only reported tokens and limit readings travel between hosts. Costs, balances, sessions and paths stay on their machines. Cost isn't reported." }) })) : limitsShown ? (_jsxs("p", { className: "usage-limits-foot", "data-region": "footer", children: ["Limits and accounts stay on ", content.host, ". Relay reads tokens from other hosts, but doesn\u2019t pull their account limits here. Cost isn\u2019t reported."] })) : null] }));
|
|
241
|
+
};
|
|
242
|
+
//# sourceMappingURL=usage-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-page.js","sourceRoot":"","sources":["../../src/views/usage-page.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,gBAAgB,EAIhB,WAAW,EAEX,QAAQ,EAER,UAAU,EAEX,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACvE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACxE,OAAO,KAAK,WAAW,MAAM,+BAA+B,CAAA;AAC5D,OAAO,EAAqC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC9F,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,EAAE,uBAAuB,EAAuB,MAAM,sBAAsB,CAAA;AAEnF,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAA;AAG3E,8GAA8G;AAC9G,MAAM,CAAC,MAAM,UAAU,GAGlB;IACH,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACjC,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACjC,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;CACpC,CAAA;AAyCD,MAAM,iBAAiB,GAAG,WAAW,CAAA;AAErC,sGAAsG;AACtG,MAAM,YAAY,GAAG,CACnB,IAAoD,EACpD,OAAgB,EAChB,QAAkC,EAClC,OAAe,EACf,EAAE;IACF,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAA2D,WAAW,CAAC,OAAO,EAAE,CAAC,CAAA;IACrH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,IAAI,OAAO,GAAG,IAAI,CAAA;QAClB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC/B,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;YAChF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACrC,IAAI,CAAC,OAAO;gBAAE,OAAM;YACpB,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;QAClH,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QACjD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAClC,OAAO,GAAG,EAAE;YACV,OAAO,GAAG,KAAK,CAAA;YACf,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;QACxC,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;IACtC,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,MAAM,WAAW,GAAG,CAAqC,KAAQ,EAAE,IAAmB,EAAK,EAAE,CAC3F,IAAI,KAAK,IAAI;IACX,CAAC,CAAC,KAAK;IACP,CAAC,CAAC;QACE,GAAG,KAAK;QACR,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;QACrF,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;KAC5F,CAAA;AAEP,yGAAyG;AACzG,MAAM,kBAAkB,GAAG,CAAC,KAAiB,EAAE,MAAmB,EAAW,EAAE;IAC7E,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IACtH,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IAC7E,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IAC9E,OAAO,CACL,UAAU,CAAC,IAAI,GAAG,CAAC;QACnB,UAAU,CAAC,IAAI,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM;QACtC,UAAU,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,MAAM;QACvC,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI;QACnC,CAAC,GAAG,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrD,KAAK,CAAC,KAAK,CAAC,KAAK,CACf,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CACd,OAAO,CAAC,IAAI,KAAK,MAAM;YACvB,OAAO,CAAC,OAAO,KAAK,CAAC;YACrB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YACjC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CACpC;QACD,MAAM,CAAC,KAAK,CAAC,KAAK,CAChB,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,OAAO,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CACxG,CACF,CAAA;AACH,CAAC,CAAA;AAED,MAAM,WAAW,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAGxE,CAAA;AAKD,MAAM,UAAU,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,EAAyC,CAAA;AACnG,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,qBAAqB,EAAE,CAAC,EAAE,CAAC,CAAA;AAC9F,MAAM,YAAY,GAAG;IACnB,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,oBAAoB;IACjC,OAAO,EAAE,WAAW;IACpB,cAAc,EAAE,gBAAgB;IAChC,gBAAgB,EAAE,mBAAmB;CAC6B,CAAA;AAEpE,iGAAiG;AACjG,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EACxB,OAAO,EACP,IAAI,EACJ,MAAM,EACN,KAAK,EAMN,EAAgB,EAAE;IACjB,MAAM,SAAS,GAAG,KAAK,EAAE,CAAA;IACzB,MAAM,MAAM,GAAG,KAAK,EAAE,CAAA;IACtB,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,KAAK,SAAS,CAAC,CAAA;IACpF,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC/C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACzC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,eAAe,KAAK,SAAS,CAAC,CAAA;QACxE,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAA;QACtD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAA;IACxE,CAAC,EAAE,EAAE,CAAC,CAAA;IACN,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAA;IAC/B,MAAM,OAAO,GAAG,OAAO,CACrB,GAAG,EAAE,CAAC,uBAAuB,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,EACjF,CAAC,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,CAChC,CAAA;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9E,MAAM,KAAK,GAAG,SAAS,EAAE,KAAK,IAAI,IAAI,CAAA;IACtC,MAAM,QAAQ,GAAG,SAAS,EAAE,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAA;IAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;IAC5G,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,IAAI,OAAO,IAAI,SAAS,KAAK,IAAI,CAAA;IAC7D,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAA;IACrE,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI,IAAI,KAAK,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IACpG,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;IAC/D,MAAM,aAAa,GAAG,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IACjE,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAA;IAChC,MAAM,KAAK,GACT,IAAI,KAAK,QAAQ;QACjB,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC;QAC5B,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC;QAC7B,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC3D,MAAM,QAAQ,GAAG,WAAW,EAAE,QAAQ,CAAA;IACtC,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,CAAA;QACjC,OAAO,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAA;IAChC,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;IACnC,MAAM,UAAU,GAAG,WAAW,EAAE,UAAU,CAAA;IAC1C,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAA;QAC/C,OAAO,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAA;IAClC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAA;IACpC,MAAM,UAAU,GAAG;QACjB,GAAG,IAAI,GAAG,CAAC;YACT,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/D,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAClE,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3F,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/F,CAAC;KACH,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpC,MAAM,aAAa,GACjB,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC;QAC5B,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW;QAC7B,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAA;IAC1F,MAAM,WAAW,GACf,SAAS,EAAE,IAAI,KAAK,IAAI;QACxB,SAAS,EAAE,IAAI,KAAK,SAAS;QAC7B,aAAa;QACb,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;IAClF,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,IAAI,IAAI,CAAC,CAAA;IACnE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC;YAAE,OAAM;QACtD,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAC7D,IAAI,WAAW;YAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACzC,IAAI,SAAS,CAAC,QAAQ,EAAE,KAAK,KAAK;YAAE,OAAM;QAC1C,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,IAAI,WAAW;YAAE,WAAW,CAAC,IAAI,CAAC,CAAA;QAC9D,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAA;IAC7C,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;IAC9C,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC;QAC3B,OAAO,CACL,mBAAS,SAAS,EAAC,eAAe,qBAAkB,IAAI,aACtD,6CAA0B,EAC1B,qEAAiD,IACzC,CACX,CAAA;IACH,MAAM,eAAe,GAAG,CAAC,IAAoB,EAAE,EAAE;QAC/C,WAAW,CAAC,KAAK,CAAC,CAAA;QAClB,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;QACjF,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;YAAE,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACpD,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;IACzC,CAAC,CAAA;IACD,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC1D,GAAG,QAAQ;QACX,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;KACjD,CAAC,CAAC,CAAA;IACH,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC5D,GAAG,QAAQ;QACX,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;KACjD,CAAC,CAAC,CAAA;IACH,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAA;IAChE,MAAM,UAAU,GACd,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAChC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;KACnH,CAAC,CAAC,IAAI,EAAE,CAAA;IACX,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAA;IAChE,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACvE,MAAM,aAAa,GAAG,YAAY,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,IAAI,CAAA;IAC9D,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAA;IAChD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAA;IAC7C,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,aAAa,EAAE,WAAW,EAAE;YAAE,SAAQ;QACtG,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC7C,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;YACnF,MAAM,KAAK,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAA;YACxD,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;QACrE,CAAC;IACH,CAAC;IACD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,OAAO,CAAA;IAChF,MAAM,OAAO,GACX,OAAO,CAAC,MAAM,KAAK,CAAC;QAClB,CAAC,CAAC,oCAAoC;QACtC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,UAAU,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,SAAS,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,GAAG,CAAA;IAChO,0FAA0F;IAC1F,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IAC5D,MAAM,QAAQ,GAAkB;QAC9B,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE;QACvD,YAAY,EAAE,KAAK;QACnB,KAAK;QACL,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC;QAClF,KAAK,EAAE,UAAU,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC;QAC7C,MAAM,EAAE,WAAW,CAAC,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC;KACjD,CAAA;IACD,+FAA+F;IAC/F,MAAM,QAAQ,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,CACtC,4BAAgB,aAAa,EAAC,SAAS,EAAE,SAAS,iBAAc,MAAM,YACnE,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACzB,YAEE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,kBACzD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,sBAClC,KAAK,CAAC,EAAE,YAEzB,KAAK,CAAC,KAAK,IALP,KAAK,CAAC,EAAE,CAMX,CACL,CAAC,GACE,CACP,CAAA;IACD,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,aAAa,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,CAAA;IAChH,MAAM,WAAW,GAAG,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,aAAa,EAAE,WAAW,EAAE,CAAC,CAAA;IACpH,MAAM,SAAS,GACb,WAAW,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC7G,IAAI,KAAK,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,CACX,eAAK,SAAS,EAAC,kBAAkB,aAC/B,eAAK,SAAS,EAAC,oBAAoB,aACjC,cAAK,SAAS,EAAC,mBAAmB,iBAAa,MAAM,sBAE/C,EACN,6CAAqB,WAAW,CAAC,IAAI,gDAA6C,IAC9E,EACL,QAAQ,CAAC,kBAAkB,CAAC,IACzB,CACP,CAAA;QACD,OAAO,CACL,eAAK,SAAS,EAAC,oBAAoB,qBAAiB,QAAQ,sBAAkB,MAAM,gBAAY,cAAc,aAE5G,aAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAC,oBAAoB,sBAE5C,EACJ,WAAW,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,YAAY,CAAC,EACxF,mBAAS,SAAS,EAAC,oBAAoB,iBAAa,QAAQ,aAC1D,KAAC,aAAa,KAAG,EACjB,iDAA8B,EAC9B,wBAAI,WAAW,CAAC,IAAI,2EAAmE,EACvF,YACE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EACvE,SAAS,EAAC,oBAAoB,iBAClB,QAAQ,yCAGlB,IACI,IACN,CACP,CAAA;IACH,CAAC;IACD,MAAM,WAAW,GAAG,CAClB,eAAK,SAAS,EAAC,oBAAoB,aACjC,kBAAQ,SAAS,EAAC,qBAAqB,aACrC,aAAI,EAAE,EAAE,SAAS,sBAAY,EAC7B,sEAAkD,EACjD,QAAQ,CAAC,CAAC,CAAC,qFAAiE,CAAC,CAAC,CAAC,IAAI,IAC7E,EACR,QAAQ,CAAC,oBAAoB,CAAC,IAC3B,CACP,CAAA;IACD,gHAAgH;IAChH,yEAAyE;IACzE,MAAM,UAAU,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACjF,OAAO,CACL,eAAK,SAAS,EAAC,eAAe,qBAAkB,IAAI,aACjD,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,CACrB,WAAW,CACZ,CAAC,CAAC,CAAC,CACF,8BACE,aAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAC,oBAAoB,sBAE5C,EACL,cAAK,SAAS,EAAC,yBAAyB,GAAG,EAC1C,YAAY,CAEX,eAAK,SAAS,EAAC,kBAAkB,aAC/B,eAAK,SAAS,EAAC,oBAAoB,aACjC,cAAK,SAAS,EAAC,mBAAmB,iBAAa,MAAM,sBAE/C,EACN,sEAAkD,EACjD,QAAQ,CAAC,CAAC,CAAC,qFAAiE,CAAC,CAAC,CAAC,IAAI,IAChF,EACL,QAAQ,CAAC,kBAAkB,CAAC,IACzB,EACN,UAAU,CACX,IACA,CACJ,EACA,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC1B,eAAK,SAAS,EAAC,wBAAwB,aACrC,iBAAO,OAAO,EAAE,MAAM,qBAEpB,kBACE,EAAE,EAAE,MAAM,EACV,IAAI,EAAC,YAAY,EACjB,KAAK,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,CAAC,EACxE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,eAAe,CAAC,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,aAG3F,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CACpB,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,CACvB,iBAAQ,KAAK,EAAC,EAAE,iCAA0B,CAC3C,CAAC,CAAC,CAAC,IAAI,CACT,CAAC,CAAC,CAAC,CACF,iBAAQ,KAAK,EAAC,EAAE,0BAAmB,CACpC,EACA,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACxB,iBAAmB,KAAK,EAAE,IAAI,YAC3B,IAAI,IADM,IAAI,CAER,CACV,CAAC,EACD,YAAY,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAC7D,iBAAQ,KAAK,EAAE,YAAY,YAAG,YAAY,GAAU,CACrD,CAAC,CAAC,CAAC,IAAI,IACD,EACR,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IACrC,EACR,KAAC,WAAW,kBACC,OAAO,EAClB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,EAC9E,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE;4BACvB,MAAM,IAAI,GAAG,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;4BAChF,IAAI,IAAI,KAAK,IAAI;gCAAE,eAAe,CAAC,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;wBACnF,CAAC,GACD,EACF,gBAAM,SAAS,EAAC,yBAAyB,4BAAa,QAAQ,IAAQ,EACrE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CACtB,YAAG,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,YAAY,iDAEvD,CACL,CAAC,CAAC,CAAC,IAAI,EACP,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,WAAW,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CACtF,KAAC,MAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,GAAG,CAAC,CAAC,sBAAgB,CAC9E,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,EACA,IAAI,KAAK,SAAS;gBACnB,WAAW,EAAE,IAAI,KAAK,MAAM;gBAC5B,KAAK,CAAC,OAAO;gBACb,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,CACzC,KAAC,UAAU,IACT,SAAS,EAAC,wBAAwB,EAClC,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,SAAS,EACd,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,SAAS,EACd,KAAK,EAAE,eAAe,WAAW,CAAC,KAAK,CAAC,sBAAsB,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,GAC3G,CACH,CAAC,CAAC,CAAC,IAAI,EACP,IAAI,KAAK,SAAS,IAAI,WAAW,EAAE,IAAI,KAAK,MAAM,IAAI,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CACpF,eAAK,SAAS,EAAC,sBAAsB,EAAC,IAAI,EAAC,QAAQ,aACjD,0BACE,KAAC,UAAU,IAAC,KAAK,EAAC,uBAAkB,EAAC,IAAI,EAAC,SAAS,EAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,SAAS,GAAG,EACjF,WAAW,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACrC,+CACmB,GAAG,EACpB,eAAM,QAAQ,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,YACjE,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;4CAClE,IAAI,EAAE,SAAS;4CACf,MAAM,EAAE,SAAS;4CACjB,QAAQ;yCACT,CAAC,GACG,uBACW,iBAAiB,SAC9B,CACR,IACG,EACN,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,GAAG,CAAC,CAAC,sBAErF,IACL,CACP,CAAC,CAAC,CAAC,IAAI,EACP,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CACpB,mBAAS,SAAS,EAAC,qCAAqC,gBAAY,SAAS,aAC3E,aAAI,SAAS,EAAC,uBAAuB,wBAAa,EAClD,eAAK,SAAS,EAAC,uBAAuB,aACpC,iBAAQ,SAAS,EAAC,qBAAqB,YACpC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,GAChE,EACT,sBACG,WAAW,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAC9B,8BACG,aAAa,aAAS,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAQ,GAAG,EAC7E,eAAM,QAAQ,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,YACjE,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;gDAClE,IAAI,EAAE,SAAS;gDACf,MAAM,EAAE,SAAS;gDACjB,QAAQ;6CACT,CAAC,GACG,IACN,CACJ,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAC9B,WAAW,CAAC,MAAM,CACnB,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAC9B,GAAG,WAAW,CAAC,IAAI,KAAK,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAC3D,CAAC,CAAC,CAAC,CACF,mCAAmC,CACpC,GACC,IACA,EACN,+BAAmB,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,wBAAwB,aAAa,EAAE,aACvG,0BACE,yBACE,aAAI,KAAK,EAAC,KAAK,+BAAoB,EACnC,aAAI,KAAK,EAAC,KAAK,uBAAY,EAC3B,aAAI,KAAK,EAAC,KAAK,sBAAW,EAC1B,aAAI,KAAK,EAAC,KAAK,4BAAiB,IAC7B,GACC,EACR,0BACG,CAAC,GAAG,WAAW,CAAC;qCACd,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC;qCAC3C,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CACxB,yBACE,aAAI,KAAK,EAAC,KAAK,YAAE,KAAK,GAAM,EAC5B,uBAAK,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,GAAM,EACjC,uBACG,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,CAAC;gDACpC,CAAC,CAAC,IAAI;gDACN,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GACrD,EACL,aAAI,SAAS,EAAC,qBAAqB,YACjC,kCACc,MAAM,EAClB,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,GAAG,GAC7E,GACC,KAdE,KAAK,CAeT,CACN,CAAC,GACE,IACF,EACR,yIAGI,EACH,KAAK,KAAK,IAAI;wBACf,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW;4BACtB,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;4BACjC,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC/C,qGAAiF,CAClF,IACO,CACX,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CACtB,4BACE,KAAC,mBAAmB,IAClB,IAAI,EAAE,OAAO,CAAC,IAAI,EAClB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,OAAO,CAAC,GAAG,EAChB,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,GAAG,CAAC,CAAC,EACrD,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAC3E,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,IAAI,GAClC,GACD,CACJ,CAAC,CAAC,CAAC,CACF,KAAC,QAAQ,OAAK,QAAQ,GAAI,CAC3B,EACA,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CACnB,8BACE,mBAAS,SAAS,EAAC,uBAAuB,gBAAY,SAAS,aAC7D,mCAAgB,EAChB,sBAAI,OAAO,GAAK,EAChB,yBACG,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACxB,yBACE,2BACE,2BAAS,IAAI,CAAC,IAAI,GAAU,EAC3B,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAC9B,gBAAM,QAAQ,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,qBAC9D,GAAG,EACP,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;gEACnE,IAAI,EAAE,SAAS;gEACf,MAAM,EAAE,SAAS;gEACjB,QAAQ;6DACT,CAAC,EAAE,GAAG,SACH,QAAQ,IACP,CACR,CAAC,CAAC,CAAC,CACF,0BAAQ,IAAI,CAAC,OAAO,CAAC,MAAM,GAAS,CACrC,IACI,EACP,2BAAS,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAU,KAjBxE,IAAI,CAAC,IAAI,CAkBb,CACN,CAAC,EACD,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACtC,yBACE,2BACE,2BAAS,OAAO,CAAC,IAAI,GAAU,EAC/B,0BAAQ,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,GAAS,IACxC,EACP,uCAAwB,KALjB,OAAO,CAAC,IAAI,CAMhB,CACN,CAAC,IACC,EACJ,KAAK,KAAK,IAAI;gCACf,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CACpG,mEAA+C,CAChD,CAAC,CAAC,CAAC,IAAI,IACA,EACV,mBAAS,SAAS,EAAC,uBAAuB,gBAAY,aAAa,aACjE,uCAAoB,EACpB,sBACG,aAAa,KAAK,IAAI;oCACrB,CAAC,CAAC,uCAAuC;oCACzC,CAAC,CAAC,MAAM,aAAa,6BAA6B,GAClD,EACJ,uBACG,CAAC,GAAG,cAAc,CAAC;qCACjB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;qCACtC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CACvB,yBACE,yBAAO,KAAK,GAAQ,EACpB,2BAAS,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAU,KAFjC,KAAK,CAGT,CACN,CAAC,GACD,IACG,EACV,mBAAS,SAAS,EAAC,uBAAuB,gBAAY,oBAAoB,aACxE,8CAA2B,EAC3B,sBACG,aAAa,KAAK,IAAI;oCACrB,CAAC,CAAC,8CAA8C;oCAChD,CAAC,CAAC,MAAM,aAAa,mDAAmD,GACxE,EACJ,uBACG,CAAC,GAAG,WAAW,CAAC;qCACd,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;qCACtC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CACvB,yBACE,yBAAO,KAAK,GAAQ,EACpB,2BAAS,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAU,KAFjC,KAAK,CAGT,CACN,CAAC,GACD,IACG,IACT,CACJ,CAAC,CAAC,CAAC,IAAI,EACP,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CACnB,iBAAQ,SAAS,EAAC,sBAAsB,YACtC,yKAGI,GACG,CACV,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAChB,aAAG,SAAS,EAAC,mBAAmB,iBAAa,QAAQ,6CACtB,OAAO,CAAC,IAAI,yHAEvC,CACL,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Result, Schema } from "effect";
|
|
2
|
+
export declare const UsageSelection: Schema.Struct<{
|
|
3
|
+
readonly range: Schema.Literals<readonly ["24h", "7d", "30d"]>;
|
|
4
|
+
readonly timeZone: Schema.String;
|
|
5
|
+
readonly host: Schema.NullOr<Schema.String>;
|
|
6
|
+
}>;
|
|
7
|
+
export type UsageSelection = typeof UsageSelection.Type;
|
|
8
|
+
declare const UsageSelectionError_base: Schema.Class<UsageSelectionError, Schema.TaggedStruct<"UsageSelectionError", {
|
|
9
|
+
readonly reason: Schema.Literal<"invalid_default_time_zone">;
|
|
10
|
+
}>, import("effect/Cause").YieldableError>;
|
|
11
|
+
export declare class UsageSelectionError extends UsageSelectionError_base {
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The shell keeps selectors in the document query. Each invalid field resets independently;
|
|
15
|
+
* valid fields survive repairs and unrelated selectors are removed. Only the active Usage page
|
|
16
|
+
* may replace history with this result. A caller must supply a real named viewer zone.
|
|
17
|
+
*/
|
|
18
|
+
export declare const canonicalUsageSelection: (search: URLSearchParams, viewerTimeZone: string) => Result.Result<{
|
|
19
|
+
readonly selection: UsageSelection;
|
|
20
|
+
readonly search: URLSearchParams;
|
|
21
|
+
readonly repaired: boolean;
|
|
22
|
+
}, UsageSelectionError>;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=usage-selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-selection.d.ts","sourceRoot":"","sources":["../../src/views/usage-selection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAYzD,eAAO,MAAM,cAAc;;;;EAIzB,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAA;;;;AAEvD,qBAAa,mBAAoB,SAAQ,wBAEvC;CAAG;AAEL;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,WAC1B,eAAe,kBACP,MAAM,KACrB,MAAM,CAAC,MAAM,CAAC;IACf,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAA;IAClC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAC3B,EAAE,mBAAmB,CAqBrB,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { UsagePreset, UsageTimeZone } from "@knpkv/herdr-connect/usage";
|
|
2
|
+
import { FleetHostName } from "@knpkv/herdr-fleet/model";
|
|
3
|
+
import { DateTime, Option, Result, Schema } from "effect";
|
|
4
|
+
const NamedZone = UsageTimeZone.check(Schema.makeFilter((zone) => Option.isSome(DateTime.zoneMakeNamed(zone))));
|
|
5
|
+
const Query = Schema.fromURLSearchParams(Schema.Struct({
|
|
6
|
+
range: Schema.optionalKey(UsagePreset),
|
|
7
|
+
timeZone: Schema.optionalKey(NamedZone),
|
|
8
|
+
host: Schema.optionalKey(FleetHostName)
|
|
9
|
+
}));
|
|
10
|
+
const RangeQuery = Schema.fromURLSearchParams(Schema.Struct({ range: Schema.optionalKey(UsagePreset) }));
|
|
11
|
+
const ZoneQuery = Schema.fromURLSearchParams(Schema.Struct({ timeZone: Schema.optionalKey(NamedZone) }));
|
|
12
|
+
const HostQuery = Schema.fromURLSearchParams(Schema.Struct({ host: Schema.optionalKey(FleetHostName) }));
|
|
13
|
+
export const UsageSelection = Schema.Struct({
|
|
14
|
+
range: UsagePreset,
|
|
15
|
+
timeZone: NamedZone,
|
|
16
|
+
host: Schema.NullOr(FleetHostName)
|
|
17
|
+
});
|
|
18
|
+
export class UsageSelectionError extends Schema.TaggedError()("UsageSelectionError", {
|
|
19
|
+
reason: Schema.Literal("invalid_default_time_zone")
|
|
20
|
+
}) {
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The shell keeps selectors in the document query. Each invalid field resets independently;
|
|
24
|
+
* valid fields survive repairs and unrelated selectors are removed. Only the active Usage page
|
|
25
|
+
* may replace history with this result. A caller must supply a real named viewer zone.
|
|
26
|
+
*/
|
|
27
|
+
export const canonicalUsageSelection = (search, viewerTimeZone) => {
|
|
28
|
+
const zone = Schema.decodeUnknownResult(NamedZone)(viewerTimeZone);
|
|
29
|
+
if (Result.isFailure(zone))
|
|
30
|
+
return Result.fail(new UsageSelectionError({ reason: "invalid_default_time_zone" }));
|
|
31
|
+
const decoded = Schema.decodeUnknownResult(Query, { onExcessProperty: "error" })(search);
|
|
32
|
+
const range = Schema.decodeUnknownResult(RangeQuery)(search);
|
|
33
|
+
const timeZone = Schema.decodeUnknownResult(ZoneQuery)(search);
|
|
34
|
+
const host = Schema.decodeUnknownResult(HostQuery)(search);
|
|
35
|
+
const selection = Result.isSuccess(decoded)
|
|
36
|
+
? {
|
|
37
|
+
range: decoded.success.range ?? "7d",
|
|
38
|
+
timeZone: decoded.success.timeZone ?? zone.success,
|
|
39
|
+
host: decoded.success.host ?? null
|
|
40
|
+
}
|
|
41
|
+
: {
|
|
42
|
+
range: Result.isSuccess(range) ? range.success.range ?? "7d" : "7d",
|
|
43
|
+
timeZone: Result.isSuccess(timeZone) ? timeZone.success.timeZone ?? zone.success : zone.success,
|
|
44
|
+
host: Result.isSuccess(host) ? host.success.host ?? null : null
|
|
45
|
+
};
|
|
46
|
+
const canonical = new URLSearchParams({ range: selection.range, timeZone: selection.timeZone });
|
|
47
|
+
if (selection.host !== null)
|
|
48
|
+
canonical.set("host", selection.host);
|
|
49
|
+
return Result.succeed({ selection, search: canonical, repaired: Result.isFailure(decoded) });
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=usage-selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-selection.js","sourceRoot":"","sources":["../../src/views/usage-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAEzD,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;AAC/G,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC;IACrD,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC;CACxC,CAAC,CAAC,CAAA;AACH,MAAM,UAAU,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAA;AACxG,MAAM,SAAS,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAA;AACxG,MAAM,SAAS,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAA;AAExG,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1C,KAAK,EAAE,WAAW;IAClB,QAAQ,EAAE,SAAS;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;CACnC,CAAC,CAAA;AAGF,MAAM,OAAO,mBAAoB,SAAQ,MAAM,CAAC,WAAW,EAAuB,CAAC,qBAAqB,EAAE;IACxG,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,2BAA2B,CAAC;CACpD,CAAC;CAAG;AAEL;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,MAAuB,EACvB,cAAsB,EAKA,EAAE;IACxB,MAAM,IAAI,GAAG,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,CAAA;IAClE,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,mBAAmB,CAAC,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC,CAAC,CAAA;IAChH,MAAM,OAAO,GAAG,MAAM,CAAC,mBAAmB,CAAC,KAAK,EAAE,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;IACxF,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;IAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAA;IAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAA;IAC1D,MAAM,SAAS,GAAmB,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC;QACzD,CAAC,CAAC;YACA,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI;YACpC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO;YAClD,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI;SACnC;QACD,CAAC,CAAC;YACA,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI;YACnE,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO;YAC/F,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI;SAChE,CAAA;IACH,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC/F,IAAI,SAAS,CAAC,IAAI,KAAK,IAAI;QAAE,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;IAClE,OAAO,MAAM,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;AAC9F,CAAC,CAAA"}
|