@schlessera/brain-ui-server 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/activity/digest.d.ts +29 -0
  2. package/dist/activity/digest.d.ts.map +1 -0
  3. package/dist/activity/digest.js +61 -0
  4. package/dist/activity/digest.js.map +1 -0
  5. package/dist/activity/notify.d.ts +62 -0
  6. package/dist/activity/notify.d.ts.map +1 -0
  7. package/dist/activity/notify.js +171 -0
  8. package/dist/activity/notify.js.map +1 -0
  9. package/dist/activity/push-sender.d.ts +63 -0
  10. package/dist/activity/push-sender.d.ts.map +1 -0
  11. package/dist/activity/push-sender.js +131 -0
  12. package/dist/activity/push-sender.js.map +1 -0
  13. package/dist/activity/query.d.ts +16 -0
  14. package/dist/activity/query.d.ts.map +1 -0
  15. package/dist/activity/query.js +128 -0
  16. package/dist/activity/query.js.map +1 -0
  17. package/dist/activity/recorder.d.ts +48 -0
  18. package/dist/activity/recorder.d.ts.map +1 -0
  19. package/dist/activity/recorder.js +205 -0
  20. package/dist/activity/recorder.js.map +1 -0
  21. package/dist/activity/runtime.d.ts +31 -0
  22. package/dist/activity/runtime.d.ts.map +1 -0
  23. package/dist/activity/runtime.js +109 -0
  24. package/dist/activity/runtime.js.map +1 -0
  25. package/dist/activity/span-sink.d.ts +22 -0
  26. package/dist/activity/span-sink.d.ts.map +1 -0
  27. package/dist/activity/span-sink.js +138 -0
  28. package/dist/activity/span-sink.js.map +1 -0
  29. package/dist/activity/store.d.ts +207 -0
  30. package/dist/activity/store.d.ts.map +1 -0
  31. package/dist/activity/store.js +440 -0
  32. package/dist/activity/store.js.map +1 -0
  33. package/dist/activity/stream.d.ts +45 -0
  34. package/dist/activity/stream.d.ts.map +1 -0
  35. package/dist/activity/stream.js +312 -0
  36. package/dist/activity/stream.js.map +1 -0
  37. package/dist/app.d.ts.map +1 -1
  38. package/dist/app.js +16 -0
  39. package/dist/app.js.map +1 -1
  40. package/dist/cron/scheduler.d.ts.map +1 -1
  41. package/dist/cron/scheduler.js +20 -5
  42. package/dist/cron/scheduler.js.map +1 -1
  43. package/dist/db/client.d.ts.map +1 -1
  44. package/dist/db/client.js +32 -6
  45. package/dist/db/client.js.map +1 -1
  46. package/dist/index.d.ts +4 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +7 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/routes/activity.d.ts +20 -0
  51. package/dist/routes/activity.d.ts.map +1 -0
  52. package/dist/routes/activity.js +300 -0
  53. package/dist/routes/activity.js.map +1 -0
  54. package/dist/routes/push.d.ts +6 -0
  55. package/dist/routes/push.d.ts.map +1 -0
  56. package/dist/routes/push.js +73 -0
  57. package/dist/routes/push.js.map +1 -0
  58. package/dist/routes/sessions.d.ts.map +1 -1
  59. package/dist/routes/sessions.js +20 -4
  60. package/dist/routes/sessions.js.map +1 -1
  61. package/dist/ws/bridge.d.ts +2 -1
  62. package/dist/ws/bridge.d.ts.map +1 -1
  63. package/dist/ws/bridge.js +27 -2
  64. package/dist/ws/bridge.js.map +1 -1
  65. package/dist/ws/connection.d.ts.map +1 -1
  66. package/dist/ws/connection.js +9 -1
  67. package/dist/ws/connection.js.map +1 -1
  68. package/dist/ws/dispatch.d.ts.map +1 -1
  69. package/dist/ws/dispatch.js +11 -0
  70. package/dist/ws/dispatch.js.map +1 -1
  71. package/dist/ws/host.d.ts +16 -0
  72. package/dist/ws/host.d.ts.map +1 -1
  73. package/dist/ws/host.js +2 -0
  74. package/dist/ws/host.js.map +1 -1
  75. package/dist/ws/run-session.d.ts.map +1 -1
  76. package/dist/ws/run-session.js +21 -1
  77. package/dist/ws/run-session.js.map +1 -1
  78. package/migrations/007_activity.sql +114 -0
  79. package/migrations/008_push_subscriptions.sql +24 -0
  80. package/package.json +5 -3
  81. package/src/activity/digest.ts +92 -0
  82. package/src/activity/notify.ts +285 -0
  83. package/src/activity/push-sender.ts +215 -0
  84. package/src/activity/query.ts +160 -0
  85. package/src/activity/recorder.ts +261 -0
  86. package/src/activity/runtime.ts +141 -0
  87. package/src/activity/span-sink.ts +152 -0
  88. package/src/activity/store.ts +774 -0
  89. package/src/activity/stream.ts +366 -0
  90. package/src/app.ts +17 -0
  91. package/src/cron/scheduler.ts +28 -8
  92. package/src/db/client.ts +31 -6
  93. package/src/index.ts +22 -0
  94. package/src/routes/activity.ts +363 -0
  95. package/src/routes/push.ts +90 -0
  96. package/src/routes/sessions.ts +24 -4
  97. package/src/ws/bridge.ts +29 -2
  98. package/src/ws/connection.ts +9 -1
  99. package/src/ws/dispatch.ts +13 -0
  100. package/src/ws/host.ts +18 -0
  101. package/src/ws/run-session.ts +28 -1
@@ -0,0 +1,138 @@
1
+ /**
2
+ * The span-sink JSONL contract: how an agent-running cron step reports its
3
+ * activity to the wrapper that records the run.
4
+ *
5
+ * The wrapper (brain-ui's cron-run.ts) exports a file path in
6
+ * `BRAIN_ACTIVITY_SPAN_SINK`; the child process appends one JSON object per
7
+ * line and never reads the file back. The wrapper ingests incrementally
8
+ * (liveness) and once at exit (completeness), attaching everything under the
9
+ * run's root span. No core call site emits this yet — the contract ships
10
+ * first, fixture-verified, and producers arrive when core grows an agent
11
+ * loop (see the plan's Deferred to Follow-Up Work).
12
+ *
13
+ * Line shapes (unknown fields ignored, malformed lines skipped and counted):
14
+ *
15
+ * {"type":"span_start","spanId":"s1","name":"execute_tool Read","ts":123,
16
+ * "parentSpanId":"s0"?, "kind":"tool"?}
17
+ * {"type":"span_end","spanId":"s1","outcome":"success","ts":124,
18
+ * "reason":"..."?, "usage":{"inputTokens":1,...}?}
19
+ * {"type":"event","spanId":"s1","eventType":"text","payload":...,"ts":125}
20
+ */
21
+ import { readFileSync } from "fs";
22
+ import { SPAN_OUTCOMES } from "./store.js";
23
+ /**
24
+ * Ingest new complete lines from a span-sink file. Incremental: pass the
25
+ * previous call's `offset`; a partial trailing line is left for next time.
26
+ * A missing file is an empty result, not an error — the child may simply
27
+ * never have emitted.
28
+ */
29
+ export function ingestSpanSink(store, path, context, offset = 0) {
30
+ let text;
31
+ try {
32
+ text = readFileSync(path, "utf-8");
33
+ }
34
+ catch {
35
+ return { offset, ingested: 0, skipped: 0 };
36
+ }
37
+ if (text.length <= offset)
38
+ return { offset, ingested: 0, skipped: 0 };
39
+ const chunk = text.slice(offset);
40
+ const lastNewline = chunk.lastIndexOf("\n");
41
+ if (lastNewline === -1)
42
+ return { offset, ingested: 0, skipped: 0 };
43
+ const complete = chunk.slice(0, lastNewline);
44
+ const consumed = offset + lastNewline + 1;
45
+ let ingested = 0;
46
+ let skipped = 0;
47
+ for (const line of complete.split("\n")) {
48
+ if (!line.trim())
49
+ continue;
50
+ if (applyLine(store, line, context))
51
+ ingested++;
52
+ else
53
+ skipped++;
54
+ }
55
+ return { offset: consumed, ingested, skipped };
56
+ }
57
+ function applyLine(store, line, context) {
58
+ let parsed;
59
+ try {
60
+ parsed = JSON.parse(line);
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ if (!parsed || typeof parsed !== "object")
66
+ return false;
67
+ const spanId = str(parsed.spanId);
68
+ if (!spanId)
69
+ return false;
70
+ // Sink span ids are namespaced by run so two runs' children can never
71
+ // collide in the shared store.
72
+ const scopedId = `${context.runId}:${spanId}`;
73
+ try {
74
+ switch (parsed.type) {
75
+ case "span_start": {
76
+ const name = str(parsed.name);
77
+ if (!name)
78
+ return false;
79
+ const parent = str(parsed.parentSpanId);
80
+ store.startSpan({
81
+ spanId: scopedId,
82
+ runId: context.runId,
83
+ parentSpanId: parent ? `${context.runId}:${parent}` : context.rootSpanId,
84
+ name,
85
+ kind: parsed.kind === "subagent" ? "subagent" : "tool",
86
+ origin: "cron",
87
+ jobName: context.jobName,
88
+ startedAt: num(parsed.ts),
89
+ });
90
+ return true;
91
+ }
92
+ case "span_end": {
93
+ const outcome = str(parsed.outcome);
94
+ if (!outcome || !SPAN_OUTCOMES.includes(outcome))
95
+ return false;
96
+ return store.endSpan(scopedId, {
97
+ outcome: outcome,
98
+ reason: str(parsed.reason),
99
+ endedAt: num(parsed.ts),
100
+ usage: usageOf(parsed.usage),
101
+ });
102
+ }
103
+ case "event": {
104
+ const eventType = str(parsed.eventType);
105
+ if (!eventType)
106
+ return false;
107
+ return store.appendEvent(scopedId, eventType, parsed.payload, num(parsed.ts)) !== null;
108
+ }
109
+ default:
110
+ return false;
111
+ }
112
+ }
113
+ catch {
114
+ // A duplicate span_start (replayed line) or similar must not abort the
115
+ // whole ingest.
116
+ return false;
117
+ }
118
+ }
119
+ function str(v) {
120
+ return typeof v === "string" && v.length > 0 ? v : undefined;
121
+ }
122
+ function num(v) {
123
+ return typeof v === "number" && Number.isFinite(v) ? v : undefined;
124
+ }
125
+ function usageOf(v) {
126
+ if (!v || typeof v !== "object")
127
+ return undefined;
128
+ const u = v;
129
+ return {
130
+ inputTokens: num(u.inputTokens),
131
+ outputTokens: num(u.outputTokens),
132
+ cacheReadTokens: num(u.cacheReadTokens),
133
+ cacheCreationTokens: num(u.cacheCreationTokens),
134
+ costUsd: num(u.costUsd),
135
+ model: str(u.model),
136
+ };
137
+ }
138
+ //# sourceMappingURL=span-sink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-sink.js","sourceRoot":"","sources":["../../src/activity/span-sink.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * The activity store: the canonical record of agent activity (migration 007).
3
+ *
4
+ * Every unit of agent work — a turn, a tool call, a subagent run, a cron run —
5
+ * is a span row forming a tree per run. Spans are written AT START (a
6
+ * non-terminal row exists while the work runs — that is what makes
7
+ * glance-checks, stuck-run detection, and "what is running?" queries
8
+ * possible) and updated to a write-once terminal outcome.
9
+ *
10
+ * Ordering has two primitives, both minted here inside the write transaction:
11
+ *
12
+ * - `seq` is per-run monotonic and totally orders every delta-visible write
13
+ * within a run. A snapshot carries the run's high-water seq; a client
14
+ * discards deltas at or below it. Deltas are derived from committed rows —
15
+ * persist-then-emit — so the stream can never show what the store does not
16
+ * hold.
17
+ * - `change_id` (AUTOINCREMENT rowid of activity_changes) is the GLOBAL
18
+ * cursor. It exists because per-run seq cannot discover a run the poller
19
+ * has never seen: a foreign writer's brand-new root span is visible only
20
+ * as "a change with a higher change_id than my cursor".
21
+ *
22
+ * Every write runs under an IMMEDIATE transaction: two processes write this
23
+ * database (server + cron wrapper), and a deferred transaction losing the
24
+ * upgrade race throws SQLITE_BUSY instead of waiting. `createUiDb` sets
25
+ * `busy_timeout` so immediate transactions queue rather than throw.
26
+ *
27
+ * Nothing in here may ever fail the work being observed: callers that
28
+ * instrument live turns wrap calls in try/catch and drop on error
29
+ * (observability must not break the observed) — but the STORE itself throws
30
+ * on programmer error, because a silent half-written record is worse than a
31
+ * loud one.
32
+ */
33
+ import type { Database } from "bun:sqlite";
34
+ export declare const SPAN_OUTCOMES: readonly ["success", "error", "timeout", "cancelled", "denied", "interrupted"];
35
+ export type SpanOutcome = (typeof SPAN_OUTCOMES)[number];
36
+ export type SpanKind = "turn" | "tool" | "subagent" | "cron";
37
+ export type SpanOrigin = "session" | "cron";
38
+ /** Token usage as spans carry it — OTel GenAI attribute semantics. */
39
+ export interface SpanUsage {
40
+ inputTokens?: number;
41
+ outputTokens?: number;
42
+ cacheReadTokens?: number;
43
+ cacheCreationTokens?: number;
44
+ costUsd?: number;
45
+ model?: string;
46
+ }
47
+ export interface SpanRow {
48
+ spanId: string;
49
+ runId: string;
50
+ parentSpanId: string | null;
51
+ name: string;
52
+ kind: SpanKind;
53
+ origin: SpanOrigin;
54
+ sessionId: string | null;
55
+ jobName: string | null;
56
+ attrs: Record<string, unknown>;
57
+ startedAt: number;
58
+ waitUntil: number | null;
59
+ endedAt: number | null;
60
+ outcome: SpanOutcome | null;
61
+ outcomeReason: string | null;
62
+ usage: SpanUsage;
63
+ writer: string;
64
+ lastHeartbeatAt: number | null;
65
+ }
66
+ export interface SpanEventRow {
67
+ spanId: string;
68
+ eventIndex: number;
69
+ ts: number;
70
+ eventType: string;
71
+ payload: unknown;
72
+ truncated: boolean;
73
+ }
74
+ /** One `activity_run_rollups` row, snake→camel. */
75
+ export interface RunRollupRow {
76
+ runId: string;
77
+ origin: SpanOrigin;
78
+ name: string;
79
+ sessionId: string | null;
80
+ jobName: string | null;
81
+ startedAt: number;
82
+ endedAt: number | null;
83
+ outcome: SpanOutcome | null;
84
+ durationMs: number | null;
85
+ spanCount: number;
86
+ inputTokens: number | null;
87
+ outputTokens: number | null;
88
+ cacheReadTokens: number | null;
89
+ cacheCreationTokens: number | null;
90
+ costUsd: number | null;
91
+ failureReason: string | null;
92
+ detailPruned: boolean;
93
+ }
94
+ /** The one snake→camel mapper for rollup rows — every reader shares it. */
95
+ export declare function rowToRunRollup(r: any): RunRollupRow;
96
+ /** One committed write, as the delta stream sees it. */
97
+ export type ActivityChange = {
98
+ changeId: number;
99
+ runId: string;
100
+ seq: number;
101
+ kind: "span";
102
+ span: SpanRow;
103
+ } | {
104
+ changeId: number;
105
+ runId: string;
106
+ seq: number;
107
+ kind: "event";
108
+ event: SpanEventRow;
109
+ };
110
+ export interface StartSpanInput {
111
+ spanId: string;
112
+ runId: string;
113
+ parentSpanId?: string;
114
+ name: string;
115
+ kind: SpanKind;
116
+ origin: SpanOrigin;
117
+ sessionId?: string;
118
+ jobName?: string;
119
+ attrs?: Record<string, unknown>;
120
+ startedAt?: number;
121
+ }
122
+ export interface EndSpanInput {
123
+ outcome: SpanOutcome;
124
+ reason?: string;
125
+ endedAt?: number;
126
+ usage?: SpanUsage;
127
+ attrs?: Record<string, unknown>;
128
+ }
129
+ export interface RunSnapshot {
130
+ runId: string;
131
+ spans: SpanRow[];
132
+ events: SpanEventRow[];
133
+ /** Per-run high-water seq at the moment of the read, in the SAME
134
+ * transaction as the reads — the poller/subscriber baseline. */
135
+ highWaterSeq: number;
136
+ /** Global cursor at the same moment, for pinning a poller baseline. */
137
+ changeCursor: number;
138
+ }
139
+ export interface PruneOptions {
140
+ /** Spans of runs that ended before this are prunable (digest floor).
141
+ * Absolute epoch ms, not an offset. */
142
+ digestFloorAt: number;
143
+ /** Runs older than this are pruned REGARDLESS of the digest floor. */
144
+ hardCeilingMs: number;
145
+ now?: number;
146
+ /** Max runs pruned per call — pruning is batched so writers are not starved. */
147
+ batch?: number;
148
+ }
149
+ /** A single event payload is capped so no delta can approach the WS frame cap. */
150
+ export declare const MAX_EVENT_PAYLOAD_BYTES = 16384;
151
+ export declare const TRUNCATION_MARKER = "\u2026[truncated]";
152
+ export interface ActivityStore {
153
+ readonly writer: string;
154
+ startSpan(input: StartSpanInput): SpanRow;
155
+ /**
156
+ * Terminal write. Write-once: returns false (and writes nothing) if the
157
+ * span is already terminal or unknown. Merged-outcome precedence lives in
158
+ * the CALLER (the host merges reporter enrichment before its single
159
+ * terminal write); the store just enforces once-ness.
160
+ */
161
+ endSpan(spanId: string, input: EndSpanInput): boolean;
162
+ /** Non-terminal field updates (usage enrichment, wait boundary, attrs). */
163
+ patchSpan(spanId: string, patch: {
164
+ attrs?: Record<string, unknown>;
165
+ usage?: SpanUsage;
166
+ waitUntil?: number;
167
+ }): boolean;
168
+ appendEvent(spanId: string, eventType: string, payload: unknown, ts?: number): SpanEventRow | null;
169
+ /** External writers touch their root span so staleness is heartbeat-age based. */
170
+ heartbeat(spanId: string, at?: number): void;
171
+ /** Close every open span of a run as `outcome` (children first), reason on all. */
172
+ cascadeClose(runId: string, outcome: SpanOutcome, reason: string): number;
173
+ /** Boot sweep: close THIS writer's leftover open spans as interrupted. */
174
+ sweepOwnOrphans(): number;
175
+ /** Close open spans whose root heartbeat (or own writer liveness) went stale. */
176
+ sweepStale(staleAfterMs: number, now?: number): number;
177
+ /** Open root spans running longer than the threshold — the watchdog signal. */
178
+ findStuck(thresholdMs: number, now?: number): SpanRow[];
179
+ changesSince(changeCursor: number, limit?: number): ActivityChange[];
180
+ /**
181
+ * Changes past the cursor whose span is a TERMINAL ROOT — the notifier's
182
+ * detection query, filtered and joined SQL-side. One row per span (the
183
+ * highest change_id it appears under).
184
+ */
185
+ terminalRootChangesSince(changeCursor: number, limit?: number): Array<{
186
+ changeId: number;
187
+ span: SpanRow;
188
+ }>;
189
+ latestChangeCursor(): number;
190
+ snapshotRun(runId: string): RunSnapshot | null;
191
+ /** The run's high-water seq — what a full snapshot carries, without the reads. */
192
+ runHighWaterSeq(runId: string): number;
193
+ getSpan(spanId: string): SpanRow | null;
194
+ openRootSpans(): SpanRow[];
195
+ /** Upsert the run's rollup row from current span state (call on terminal). */
196
+ rollupRun(runId: string): void;
197
+ prune(options: PruneOptions): {
198
+ runsPruned: number;
199
+ spansDeleted: number;
200
+ };
201
+ }
202
+ export interface CreateActivityStoreOptions {
203
+ /** Process identity stamped on every span this store writes. */
204
+ writer?: string;
205
+ }
206
+ export declare function createActivityStore(db: Database, options?: CreateActivityStoreOptions): ActivityStore;
207
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/activity/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,aAAa,gFAOhB,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AAC7D,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5C,sEAAsE;AACtE,MAAM,WAAW,SAAS;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,mDAAmD;AACnD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,GAAG,YAAY,CAoBnD;AAED,wDAAwD;AACxD,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC7E;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,CAAC;AAEzF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB;qEACiE;IACjE,YAAY,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B;4CACwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,kFAAkF;AAClF,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAC9C,eAAO,MAAM,iBAAiB,sBAAiB,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC;IAC1C;;;;;OAKG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC;IACtD,2EAA2E;IAC3E,SAAS,CACP,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAChF,OAAO,CAAC;IACX,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAAC;IACnG,kFAAkF;IAClF,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,mFAAmF;IACnF,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1E,0EAA0E;IAC1E,eAAe,IAAI,MAAM,CAAC;IAC1B,iFAAiF;IACjF,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvD,+EAA+E;IAC/E,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC;IACxD,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE,CAAC;IACrE;;;;OAIG;IACH,wBAAwB,CACtB,YAAY,EAAE,MAAM,EACpB,KAAK,CAAC,EAAE,MAAM,GACb,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC9C,kBAAkB,IAAI,MAAM,CAAC;IAC7B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IAC/C,kFAAkF;IAClF,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACxC,aAAa,IAAI,OAAO,EAAE,CAAC;IAC3B,8EAA8E;IAC9E,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5E;AAED,MAAM,WAAW,0BAA0B;IACzC,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,QAAQ,EACZ,OAAO,GAAE,0BAA+B,GACvC,aAAa,CAqgBf"}