@cotal-ai/web 0.0.0 → 0.11.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.
@@ -0,0 +1,350 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Cotal · observability</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <link
10
+ href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;500;600;700&display=swap"
11
+ rel="stylesheet"
12
+ />
13
+ <style>
14
+ :root {
15
+ --bg: #0d1117; --panel: #161b22; --tile: #1c2230; --line: #21262d;
16
+ --fg: #e6edf3; --dim: #8b949e; --faint: #6e7681;
17
+ --blue: #58a6ff; --green: #3fb950; --amber: #d29922; --orange: #db6d28; --red: #f85149;
18
+ --tint-green: #1f2d24; --tint-amber: #2a2417; --peer-amber: #221e12; --tag-amber: #3a2e12;
19
+ --sel: #15233a; --intent: #10203a; --intent-badge: #16345c; --rollup: #12161d;
20
+ --font: "Work Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
21
+ }
22
+ * { box-sizing: border-box; }
23
+ html, body { height: 100%; }
24
+ body {
25
+ margin: 0; display: grid; grid-template-rows: 76px 1fr;
26
+ font-family: var(--font); font-size: 13px; line-height: 1.45;
27
+ background: var(--bg); color: var(--fg);
28
+ -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
29
+ }
30
+
31
+ /* ── Header ── */
32
+ header {
33
+ display: flex; align-items: center; gap: 20px; padding: 0 24px;
34
+ background: var(--panel); border-bottom: 1px solid var(--line);
35
+ }
36
+ .brand { display: flex; align-items: center; gap: 10px; }
37
+ .brand .mark { width: 10px; height: 10px; border-radius: 50%; background: var(--blue); }
38
+ .brand .title { font-size: 18px; font-weight: 700; color: var(--fg); }
39
+ .brand .space { font-size: 14px; color: var(--dim); }
40
+ .brand-graph {
41
+ font-size: 12px; font-weight: 600; color: var(--dim); text-decoration: none;
42
+ padding: 4px 10px; border: 1px solid var(--line); border-radius: 8px;
43
+ }
44
+ .brand-graph:hover { color: var(--fg); border-color: var(--blue); }
45
+ .pill {
46
+ display: inline-flex; align-items: center; gap: 6px; padding: 4px 9px;
47
+ border-radius: 20px; background: var(--tint-green);
48
+ }
49
+ .pill .d { width: 7px; height: 7px; border-radius: 50%; background: var(--green); }
50
+ .pill .t { font-size: 11px; font-weight: 600; color: var(--green); }
51
+ .pill.down { background: #2a1717; }
52
+ .pill.down .d { background: var(--red); } .pill.down .t { color: var(--red); }
53
+
54
+ /* HealthBand tiles */
55
+ .tiles { margin-left: auto; display: flex; gap: 10px; }
56
+ .tile {
57
+ display: flex; align-items: center; gap: 9px; padding: 8px 12px;
58
+ border-radius: 8px; background: var(--tile); border: 1px solid var(--line);
59
+ }
60
+ .tile .bar { width: 3px; height: 24px; border-radius: 2px; background: var(--faint); }
61
+ .tile .c { display: flex; flex-direction: column; gap: 1px; }
62
+ .tile .n { font-size: 17px; font-weight: 700; color: var(--fg); line-height: 1.1; }
63
+ .tile .lbl { font-size: 10.5px; color: var(--dim); letter-spacing: .3px; line-height: 1.1; }
64
+ .tile.working .bar { background: var(--green); }
65
+ .tile.waiting { background: var(--tint-amber); border-color: var(--amber); }
66
+ .tile.waiting .bar { background: var(--amber); } .tile.waiting .n { color: var(--amber); }
67
+ .tile.oldest .bar { background: var(--orange); }
68
+
69
+ /* ── Body grid ── */
70
+ main { display: grid; grid-template-columns: 300px 1fr 340px; min-height: 0; }
71
+ aside {
72
+ background: var(--panel); border-right: 1px solid var(--line);
73
+ overflow-y: auto; min-height: 0;
74
+ }
75
+ aside.rail { border-right: 0; border-left: 1px solid var(--line); }
76
+
77
+ .ghead {
78
+ display: flex; align-items: center; gap: 6px; padding: 12px 16px;
79
+ font-size: 11px; font-weight: 600; letter-spacing: .8px; color: var(--dim);
80
+ }
81
+ .ghead .c { margin-left: auto; font-size: 11px; font-weight: 400; color: var(--faint); }
82
+ .divider { height: 1px; background: var(--line); }
83
+
84
+ /* ── Roster ── */
85
+ .peer {
86
+ display: flex; gap: 9px; padding: 8px 16px; align-items: flex-start;
87
+ }
88
+ .peer.waiting { background: var(--peer-amber); border-left: 2px solid var(--amber); padding-left: 14px; }
89
+ .peer .dot { width: 7px; font-size: 11px; line-height: 19px; flex: none; text-align: center; }
90
+ .dot.working { color: var(--green); } .dot.waiting { color: var(--amber); }
91
+ .dot.idle, .dot.offline { color: var(--faint); }
92
+ .peer .c { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
93
+ .peer .l1 { display: flex; align-items: center; gap: 6px; min-width: 0; }
94
+ .peer .name { font-size: 13.5px; font-weight: 600; color: var(--fg); white-space: nowrap; }
95
+ .peer .role { font-size: 11px; color: var(--faint); white-space: nowrap;
96
+ overflow: hidden; text-overflow: ellipsis; }
97
+ .peer .act { font-size: 11.5px; color: var(--dim); white-space: nowrap;
98
+ overflow: hidden; text-overflow: ellipsis; }
99
+ .peer.waiting .act { color: var(--amber); }
100
+ .tag {
101
+ font-size: 9.5px; font-weight: 600; padding: 1px 6px; border-radius: 4px;
102
+ white-space: nowrap; background: var(--tag-amber); color: var(--amber);
103
+ }
104
+ /* A peer row is a click-through into its Agent Detail card. */
105
+ .peer.nav { cursor: pointer; }
106
+ .peer.nav:hover { background: #ffffff06; }
107
+ .peer.nav.sel { background: var(--sel); }
108
+ .peer.nav:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
109
+
110
+ /* ── Channels ── */
111
+ .chan {
112
+ display: flex; align-items: center; gap: 8px; padding: 6px 16px;
113
+ cursor: pointer;
114
+ }
115
+ .chan:hover { background: #ffffff06; }
116
+ .chan.sel { background: var(--sel); border-left: 2px solid var(--blue); padding-left: 14px; }
117
+ .chan .l { display: flex; align-items: center; gap: 7px; min-width: 0; flex: 1; }
118
+ .chan .hash { font-size: 12px; color: var(--dim); flex: none; }
119
+ .chan .glyph { font-size: 12px; color: var(--blue); flex: none; }
120
+ .chan .name { font-size: 13px; color: var(--blue); overflow: hidden;
121
+ text-overflow: ellipsis; white-space: nowrap; }
122
+ .chan.sel .name { font-weight: 600; color: var(--fg); }
123
+ .chan.muted .hash, .chan.muted .name { color: var(--faint); }
124
+ .chan .count { font-size: 11px; color: var(--faint); flex: none; }
125
+ .chan.sel .count { color: var(--dim); }
126
+ .mention {
127
+ font-size: 10px; font-weight: 700; color: var(--bg); background: var(--blue);
128
+ padding: 1px 6px; border-radius: 9px; flex: none;
129
+ }
130
+
131
+ /* ── Feed ── */
132
+ section { display: flex; flex-direction: column; min-height: 0; background: var(--bg); }
133
+ .feed-head {
134
+ display: flex; align-items: center; gap: 10px; padding: 14px 20px;
135
+ border-bottom: 1px solid var(--line); flex: none;
136
+ }
137
+ .feed-head .h { font-size: 15px; font-weight: 700; color: var(--fg); }
138
+ .feed-head .sub { font-size: 12px; color: var(--dim); }
139
+ .feed-head .ctrls { margin-left: auto; display: flex; gap: 8px; align-items: center; }
140
+ .chip {
141
+ font-size: 11px; padding: 4px 10px; border-radius: 14px; cursor: pointer;
142
+ color: var(--faint); user-select: none; border: 1px solid transparent; white-space: nowrap;
143
+ }
144
+ .chip.mode.on { background: var(--tile); border-color: var(--line); color: var(--fg); }
145
+ .chip.pause.on { color: var(--amber); }
146
+ .chip.static { cursor: default; }
147
+ .chip.danger { color: var(--red); }
148
+ .chip.danger:hover { background: #2a1717; border-color: var(--red); }
149
+
150
+ .feed { overflow-y: auto; min-height: 0; flex: 1; display: flex; flex-direction: column;
151
+ gap: 2px; padding: 8px; }
152
+ .sys { text-align: center; padding: 5px 12px; font-size: 11px; color: var(--faint); }
153
+ .msg { display: flex; gap: 10px; padding: 7px 12px; align-items: flex-start; }
154
+ .msg .ts { font-size: 11px; color: var(--faint); flex: none; width: 40px; line-height: 19px; }
155
+ .msg .badge {
156
+ font-size: 9.5px; font-weight: 600; padding: 2px 7px; border-radius: 4px;
157
+ background: var(--line); flex: none; line-height: 1.4;
158
+ }
159
+ .badge.chat { color: var(--blue); } .badge.unicast { color: var(--amber); }
160
+ .badge.anycast { color: var(--green); } .badge.intent { color: var(--blue); background: var(--intent-badge); }
161
+ .msg .c { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
162
+ .msg .l1 { display: flex; align-items: center; gap: 6px; min-width: 0; flex-wrap: wrap; }
163
+ .msg .who { font-size: 13px; font-weight: 600; color: var(--fg); }
164
+ .msg .role { font-size: 10.5px; color: var(--faint); }
165
+ .msg .tgt { font-size: 11px; color: var(--dim); }
166
+ .msg .body { font-size: 12.5px; color: var(--fg); word-break: break-word; }
167
+ .msg.intent { background: var(--intent); border-left: 2px solid var(--blue); padding-left: 10px; }
168
+ .msg.intent .tgt { color: var(--blue); }
169
+ .subpill {
170
+ font-size: 9.5px; font-weight: 600; padding: 1px 6px; border-radius: 4px;
171
+ background: var(--tint-amber); color: var(--amber); flex: none;
172
+ }
173
+ .rollup {
174
+ display: flex; align-items: center; gap: 8px; margin: 0 4px; padding: 6px 12px;
175
+ border-radius: 6px; background: var(--rollup);
176
+ }
177
+ .rollup .ar { font-size: 13px; color: var(--faint); }
178
+ .rollup .t { font-size: 11.5px; color: var(--dim); }
179
+
180
+ /* ── NEEDS YOU rail ── */
181
+ aside.rail { padding: 16px; display: flex; flex-direction: column; gap: 12px; }
182
+ .rail-head { display: flex; align-items: center; justify-content: space-between; }
183
+ .rail-head .t { font-size: 12px; font-weight: 700; color: var(--fg); letter-spacing: .8px; }
184
+ .rail-head .n {
185
+ font-size: 11px; font-weight: 700; color: var(--bg); background: var(--red);
186
+ padding: 2px 8px; border-radius: 12px;
187
+ }
188
+ .card {
189
+ border-radius: 10px; background: var(--tile); border: 1px solid var(--ac, var(--line));
190
+ padding: 14px; display: flex; flex-direction: column; gap: 9px;
191
+ }
192
+ .card.nav { cursor: pointer; transition: border-color .12s, background .12s; }
193
+ .card.nav:hover { border-color: var(--ac); }
194
+ .card.nav.sel { border-color: var(--ac); background: var(--tint-amber, var(--tile)); }
195
+ .card .top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
196
+ .card .cat-l { display: flex; align-items: center; gap: 7px; }
197
+ .card .cdot { width: 8px; height: 8px; border-radius: 50%; background: var(--ac); }
198
+ .card .cat { font-size: 10.5px; font-weight: 700; color: var(--ac); letter-spacing: .4px; }
199
+ .card .age { font-size: 10px; color: var(--dim); background: var(--line);
200
+ padding: 1px 6px; border-radius: 4px; }
201
+ .card .title { font-size: 13.5px; font-weight: 600; color: var(--fg); }
202
+ .card .crole { font-size: 11px; font-weight: 500; color: var(--faint); margin-left: 7px; }
203
+ .card .desc { font-size: 12px; color: var(--dim); }
204
+ /* Live waiting cards: one-line preview (gist at a glance); full text lives in the click-through detail. */
205
+ .card.nav .desc { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
206
+ .card .btns { display: flex; gap: 8px; }
207
+ .btn {
208
+ font-size: 11.5px; padding: 6px 12px; border-radius: 6px; cursor: pointer;
209
+ border: 1px solid transparent; white-space: nowrap;
210
+ }
211
+ .btn.primary { background: var(--ac); color: var(--bg); font-weight: 700; }
212
+ .btn.secondary { border-color: var(--line); color: var(--fg); font-weight: 500; }
213
+ .tone-amber { --ac: var(--amber); } .tone-red { --ac: var(--red); }
214
+ .tone-orange { --ac: var(--orange); } .tone-blue { --ac: var(--blue); }
215
+ .rail-foot { font-size: 10.5px; color: var(--faint); }
216
+
217
+ /* ── Channel view (center) ── */
218
+ .ch-head {
219
+ display: flex; flex-direction: column; gap: 5px; padding: 14px 20px;
220
+ background: var(--panel); border-bottom: 1px solid var(--line); flex: none;
221
+ }
222
+ .ch-head .row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
223
+ .ch-head .title { display: flex; align-items: center; gap: 8px; min-width: 0; }
224
+ .ch-head .h { font-size: 17px; font-weight: 700; color: var(--fg); }
225
+ .ch-head .sub { font-size: 11px; color: var(--faint); white-space: nowrap; }
226
+ .ch-head .purpose { font-size: 12px; color: var(--dim); }
227
+ .clist { overflow-y: auto; min-height: 0; flex: 1; display: flex; flex-direction: column;
228
+ gap: 2px; padding: 10px; }
229
+ .cmsg { display: flex; gap: 10px; padding: 7px 12px; align-items: flex-start; }
230
+ .cmsg .ts { font-size: 11px; color: var(--faint); flex: none; width: 40px; line-height: 19px; }
231
+ .cmsg .dot { font-size: 11px; flex: none; width: 14px; text-align: center; line-height: 19px; }
232
+ .cmsg .c { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
233
+ .cmsg .l1 { display: flex; align-items: center; gap: 6px; }
234
+ .cmsg .who { font-size: 13px; font-weight: 600; color: var(--fg); }
235
+ .cmsg .role { font-size: 10.5px; color: var(--faint); }
236
+ .cmsg .body { font-size: 12.5px; color: var(--fg); word-break: break-word; }
237
+ .thread {
238
+ align-self: flex-start; margin-top: 2px; font-size: 10.5px; color: var(--blue);
239
+ background: var(--line); padding: 3px 8px; border-radius: 6px;
240
+ }
241
+ .unread-mark { display: flex; align-items: center; gap: 10px; padding: 6px 12px; }
242
+ .unread-mark .line { flex: 1; height: 1px; background: var(--red); }
243
+ .unread-mark .t { font-size: 10.5px; font-weight: 600; color: var(--red); white-space: nowrap; }
244
+
245
+ .ch-head .ctrls { display: flex; align-items: center; gap: 8px; }
246
+ .cmsg .dir { font-size: 11px; color: var(--dim); }
247
+ .dtag { font-size: 9.5px; font-weight: 600; padding: 2px 7px; border-radius: 4px;
248
+ background: var(--line); color: var(--amber); }
249
+
250
+ /* ── Direct messages (sidebar lens) ── */
251
+ .dm { display: flex; align-items: center; gap: 6px; padding: 7px 16px; cursor: pointer; }
252
+ .dm:hover { background: #ffffff06; }
253
+ .dm.sel { background: var(--sel); }
254
+ .dm .caret, .dm .ln { width: 10px; flex: none; text-align: center; font-size: 9px; color: var(--faint); }
255
+ .dm .l { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; }
256
+ .dm .dot { width: 12px; flex: none; text-align: center; font-size: 11px; }
257
+ .dm .nm { font-size: 13.5px; font-weight: 600; color: var(--fg); white-space: nowrap; }
258
+ .dm .role { font-size: 11px; color: var(--faint); white-space: nowrap;
259
+ overflow: hidden; text-overflow: ellipsis; }
260
+ .dm .threads { font-size: 11px; color: var(--faint); flex: none; }
261
+ .dm.sub { padding-left: 34px; }
262
+ .dm.sub .nm { font-size: 12.5px; font-weight: 400; }
263
+ .dm.sub .dot { width: 10px; font-size: 10px; }
264
+
265
+ .empty { color: var(--faint); padding: 22px 16px; font-size: 12px; }
266
+
267
+ /* ── Agent Detail (centre drill-down) ── */
268
+ .detail { padding: 22px 24px; display: flex; flex-direction: column; gap: 13px; overflow-y: auto; }
269
+ .detail .d-head { display: flex; align-items: center; gap: 9px; }
270
+ .detail .d-head .dot { font-size: 13px; }
271
+ .detail .d-status { font-size: 11px; font-weight: 700; letter-spacing: .5px; color: var(--dim); }
272
+ .detail.amber .d-status { color: var(--amber); }
273
+ .detail .d-age { margin-left: auto; font-size: 11px; color: var(--faint); }
274
+ .detail .d-who { font-size: 20px; font-weight: 700; color: var(--fg); display: flex; align-items: baseline; }
275
+ .detail .d-who .crole { font-size: 12px; font-weight: 500; color: var(--faint); margin-left: 8px; }
276
+ .detail .d-label { font-size: 10.5px; font-weight: 600; letter-spacing: .4px; color: var(--faint); text-transform: uppercase; }
277
+ .detail .d-block { font-size: 13px; color: var(--fg); line-height: 1.5; padding: 12px 14px; border-radius: 8px;
278
+ background: var(--tile); border: 1px solid var(--line); white-space: pre-wrap; word-break: break-word; }
279
+ .detail.amber .d-block { border-color: var(--amber); background: var(--tint-amber); }
280
+ .detail .d-block.muted { color: var(--dim); }
281
+ .detail .d-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: -6px; }
282
+ .detail .d-badge {
283
+ font-size: 10.5px; font-weight: 600; padding: 2px 8px; border-radius: 5px;
284
+ background: var(--tile); border: 1px solid var(--line); color: var(--dim);
285
+ }
286
+ .detail .d-badge.model { font-family: ui-monospace, monospace; color: var(--fg); letter-spacing: -.2px; }
287
+ /* Harness (host connector) badge — brand-coloured via --hc; used in the detail view (pill
288
+ with label) and the roster row (bare icon). */
289
+ .harness-badge {
290
+ display: inline-flex; align-items: center; gap: 6px;
291
+ font-size: 11px; font-weight: 600; padding: 3px 10px 3px 8px; border-radius: 999px;
292
+ color: var(--hc); border: 1px solid color-mix(in srgb, var(--hc) 45%, transparent);
293
+ background: color-mix(in srgb, var(--hc) 15%, transparent);
294
+ }
295
+ .harness-ico { display: inline-flex; align-items: center; flex: none; }
296
+ .harness-badge svg, .harness-ico svg { width: 13px; height: 13px; display: block; }
297
+ .detail .d-desc { font-size: 13px; color: var(--fg); line-height: 1.5; }
298
+ .detail .d-sec { display: flex; flex-direction: column; gap: 7px; }
299
+ .detail .d-chips { display: flex; flex-wrap: wrap; gap: 6px; }
300
+ .detail .d-chip {
301
+ font-size: 11px; padding: 2px 9px; border-radius: 12px;
302
+ background: var(--tile); border: 1px solid var(--line); color: var(--dim);
303
+ }
304
+ .detail .d-skills { display: flex; flex-direction: column; gap: 8px; }
305
+ .detail .d-skill {
306
+ display: flex; flex-direction: column; gap: 1px; padding: 8px 12px;
307
+ border-radius: 8px; background: var(--tile); border: 1px solid var(--line);
308
+ }
309
+ .detail .d-skill .nm { font-size: 12.5px; font-weight: 600; color: var(--fg); }
310
+ .detail .d-skill .dsc { font-size: 11.5px; color: var(--dim); }
311
+ .detail .d-kv { display: flex; flex-direction: column; gap: 4px; }
312
+ .detail .d-kv .row { display: flex; gap: 10px; font-size: 12px; }
313
+ .detail .d-kv .k { color: var(--faint); min-width: 90px; flex: none; }
314
+ .detail .d-kv .v { color: var(--fg); word-break: break-word; }
315
+ .detail .d-foot {
316
+ display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 4px;
317
+ padding-top: 11px; border-top: 1px solid var(--line);
318
+ }
319
+ .detail .d-foot-item { font-size: 10.5px; color: var(--faint); }
320
+ .detail .d-foot-item.id { font-family: ui-monospace, monospace; word-break: break-all; }
321
+ </style>
322
+ </head>
323
+ <body>
324
+ <header>
325
+ <span class="brand">
326
+ <span class="mark"></span>
327
+ <span class="title">Cotal</span>
328
+ <span class="space" id="space"></span>
329
+ <span class="pill down" id="conn"><span class="d"></span><span class="t">connecting</span></span>
330
+ <a class="brand-graph" href="/graph">Graph view →</a>
331
+ </span>
332
+ <div class="tiles" id="tiles"></div>
333
+ </header>
334
+ <main id="main">
335
+ <aside>
336
+ <div class="ghead">ONLINE <span class="c" id="online-c"></span></div>
337
+ <div id="roster"></div>
338
+ <div class="divider"></div>
339
+ <div class="ghead">CHANNELS</div>
340
+ <div id="channels"></div>
341
+ <div class="divider"></div>
342
+ <div class="ghead">DIRECT MESSAGES</div>
343
+ <div id="dms"></div>
344
+ </aside>
345
+ <section id="center"></section>
346
+ <aside class="rail" id="rail"></aside>
347
+ </main>
348
+ <script src="/app.js"></script>
349
+ </body>
350
+ </html>
package/dist/web.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { type ParsedArgs } from "@cotal-ai/core";
2
+ import { type LocalProcess } from "@cotal-ai/workspace";
3
+ /** The dashboard's default port and its branded address. The server binds loopback
4
+ * (127.0.0.1) but serves any Host, so `cotal.localhost` — which Chrome/Firefox/Edge
5
+ * resolve to loopback with no DNS setup — just works. (Safari may not resolve
6
+ * `*.localhost`; plain http://127.0.0.1:7799 always does.) */
7
+ export declare const WEB_PORT = 7799;
8
+ export declare const WEB_URL = "http://cotal.localhost:7799/";
9
+ export declare const webProcess: LocalProcess;
10
+ /** A live observability dashboard for a space, served over HTTP + SSE. A read-only
11
+ * observer endpoint (invisible to peers) feeds the page presence, channel history,
12
+ * and a live message stream — no manager required. Bound to loopback. */
13
+ export declare function web(args: ParsedArgs): Promise<void>;
14
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAKA,OAAO,EAQL,KAAK,UAAU,EAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAML,KAAK,YAAY,EAElB,MAAM,qBAAqB,CAAC;AAI7B;;;+DAG+D;AAC/D,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,OAAO,iCAAwC,CAAC;AAC7D,eAAO,MAAM,UAAU,EAAE,YAMxB,CAAC;AAqDF;;0EAE0E;AAC1E,wBAAsB,GAAG,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA4MzD"}