@knpkv/herdr-connect 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/activity-store.d.ts +11 -0
- package/dist/activity-store.d.ts.map +1 -0
- package/dist/activity-store.js +76 -0
- package/dist/activity-store.js.map +1 -0
- package/dist/client-entry.d.ts +2 -0
- package/dist/client-entry.d.ts.map +1 -0
- package/dist/client-entry.js +11 -0
- package/dist/client-entry.js.map +1 -0
- package/dist/client.d.ts +86 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +453 -0
- package/dist/client.js.map +1 -0
- package/dist/directory.d.ts +159 -0
- package/dist/directory.d.ts.map +1 -0
- package/dist/directory.js +186 -0
- package/dist/directory.js.map +1 -0
- package/dist/errors.d.ts +62 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +36 -0
- package/dist/errors.js.map +1 -0
- package/dist/forest.d.ts +61 -0
- package/dist/forest.d.ts.map +1 -0
- package/dist/forest.js +90 -0
- package/dist/forest.js.map +1 -0
- package/dist/id.d.ts +4 -0
- package/dist/id.d.ts.map +1 -0
- package/dist/id.js +10 -0
- package/dist/id.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/terminal-release.d.ts +6 -0
- package/dist/internal/terminal-release.d.ts.map +1 -0
- package/dist/internal/terminal-release.js +13 -0
- package/dist/internal/terminal-release.js.map +1 -0
- package/dist/keyboard.d.ts +2 -0
- package/dist/keyboard.d.ts.map +1 -0
- package/dist/keyboard.js +19 -0
- package/dist/keyboard.js.map +1 -0
- package/dist/model.d.ts +144 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +104 -0
- package/dist/model.js.map +1 -0
- package/dist/relationship-store.d.ts +66 -0
- package/dist/relationship-store.d.ts.map +1 -0
- package/dist/relationship-store.js +246 -0
- package/dist/relationship-store.js.map +1 -0
- package/dist/target.d.ts +83 -0
- package/dist/target.d.ts.map +1 -0
- package/dist/target.js +56 -0
- package/dist/target.js.map +1 -0
- package/dist/terminal-input.d.ts +30 -0
- package/dist/terminal-input.d.ts.map +1 -0
- package/dist/terminal-input.js +95 -0
- package/dist/terminal-input.js.map +1 -0
- package/dist/terminal-setup.d.ts +10 -0
- package/dist/terminal-setup.d.ts.map +1 -0
- package/dist/terminal-setup.js +11 -0
- package/dist/terminal-setup.js.map +1 -0
- package/dist/terminal-theme.d.ts +3 -0
- package/dist/terminal-theme.d.ts.map +1 -0
- package/dist/terminal-theme.js +3 -0
- package/dist/terminal-theme.js.map +1 -0
- package/dist/terminal-viewport.d.ts +12 -0
- package/dist/terminal-viewport.d.ts.map +1 -0
- package/dist/terminal-viewport.js +21 -0
- package/dist/terminal-viewport.js.map +1 -0
- package/dist/terminal.d.ts +794 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +166 -0
- package/dist/terminal.js.map +1 -0
- package/dist/view.d.ts +51 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +210 -0
- package/dist/view.js.map +1 -0
- package/package.json +84 -0
- package/src/styles.css +527 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useAtom, useAtomMount, useAtomValue } from "@effect/atom-react";
|
|
3
|
+
import { BrowserHttpClient } from "@effect/platform-browser";
|
|
4
|
+
import { StateLabel, Surface, Text } from "@knpkv/rly/primitives";
|
|
5
|
+
import { decodeBoundedResponseJson } from "@knpkv/herdr-fleet/response";
|
|
6
|
+
import { Cause, Effect, Fiber, Result, Schedule, Schema } from "effect";
|
|
7
|
+
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
|
|
8
|
+
import * as Atom from "effect/unstable/reactivity/Atom";
|
|
9
|
+
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
10
|
+
import { FitAddon, init, Terminal } from "ghostty-web";
|
|
11
|
+
import { useEffect, useRef } from "react";
|
|
12
|
+
import { buildConnectForest } from "./forest.js";
|
|
13
|
+
import { FleetConnectAgentPage, FleetConnectAgents, TerminalServerSignal } from "./model.js";
|
|
14
|
+
import { makePendingTerminalInput, makeTouchScrollGesture, pageScrollCommand, wheelScrollCommand } from "./terminal-input.js";
|
|
15
|
+
import { AgentDirectory, connectAgentKey, ConnectWorkspace } from "./view.js";
|
|
16
|
+
import { acquireTerminalSetup } from "./terminal-setup.js";
|
|
17
|
+
import { terminalBackground } from "./terminal-theme.js";
|
|
18
|
+
import { bindTerminalViewport } from "./terminal-viewport.js";
|
|
19
|
+
import { resolveConnectPreferenceDecision } from "./target.js";
|
|
20
|
+
import { nextConnectAgentIndex } from "./keyboard.js";
|
|
21
|
+
class ConnectNetworkError extends Schema.TaggedError()("ConnectNetworkError", {
|
|
22
|
+
detail: Schema.String
|
|
23
|
+
}) {
|
|
24
|
+
}
|
|
25
|
+
class ConnectStatusError extends Schema.TaggedError()("ConnectStatusError", {
|
|
26
|
+
status: Schema.Number
|
|
27
|
+
}) {
|
|
28
|
+
}
|
|
29
|
+
class ConnectProtocolError extends Schema.TaggedError()("ConnectProtocolError", {
|
|
30
|
+
detail: Schema.String,
|
|
31
|
+
cause: Schema.Defect()
|
|
32
|
+
}) {
|
|
33
|
+
}
|
|
34
|
+
class ConnectPreferenceError extends Schema.TaggedError()("ConnectPreferenceError", {
|
|
35
|
+
operation: Schema.String,
|
|
36
|
+
cause: Schema.Defect()
|
|
37
|
+
}) {
|
|
38
|
+
}
|
|
39
|
+
class ConnectInputQueueError extends Schema.TaggedError()("ConnectInputQueueError", {
|
|
40
|
+
detail: Schema.String
|
|
41
|
+
}) {
|
|
42
|
+
}
|
|
43
|
+
const RememberedAgentKey = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(513));
|
|
44
|
+
const rememberedAgentStorageKey = "fleet-connect-agent";
|
|
45
|
+
const loadRememberedAgent = Effect.try({
|
|
46
|
+
try: () => window.localStorage.getItem(rememberedAgentStorageKey),
|
|
47
|
+
catch: (cause) => new ConnectPreferenceError({
|
|
48
|
+
operation: "local_storage.read",
|
|
49
|
+
cause
|
|
50
|
+
})
|
|
51
|
+
}).pipe(Effect.flatMap((value) => value === null
|
|
52
|
+
? Effect.succeed(null)
|
|
53
|
+
: Schema.decodeUnknownEffect(RememberedAgentKey)(value).pipe(Effect.mapError((cause) => new ConnectPreferenceError({
|
|
54
|
+
operation: "local_storage.decode",
|
|
55
|
+
cause
|
|
56
|
+
})))));
|
|
57
|
+
const storeRememberedAgent = (key) => Schema.decodeUnknownEffect(RememberedAgentKey)(key).pipe(Effect.mapError((cause) => new ConnectPreferenceError({
|
|
58
|
+
operation: "local_storage.encode",
|
|
59
|
+
cause
|
|
60
|
+
})), Effect.flatMap((value) => Effect.try({
|
|
61
|
+
try: () => window.localStorage.setItem(rememberedAgentStorageKey, value),
|
|
62
|
+
catch: (cause) => new ConnectPreferenceError({
|
|
63
|
+
operation: "local_storage.write",
|
|
64
|
+
cause
|
|
65
|
+
})
|
|
66
|
+
})));
|
|
67
|
+
const loadAgents = Effect.gen(function* () {
|
|
68
|
+
const client = yield* HttpClient.HttpClient;
|
|
69
|
+
const agents = [];
|
|
70
|
+
const failures = [];
|
|
71
|
+
let cursor = null;
|
|
72
|
+
do {
|
|
73
|
+
const path = cursor === null
|
|
74
|
+
? "/v1/connect/agents"
|
|
75
|
+
: `/v1/connect/agents?cursorHost=${encodeURIComponent(cursor.host)}&cursorId=${encodeURIComponent(cursor.id)}`;
|
|
76
|
+
const response = yield* client
|
|
77
|
+
.get(path)
|
|
78
|
+
.pipe(Effect.mapError((cause) => new ConnectNetworkError({ detail: String(cause) })));
|
|
79
|
+
if (response.status < 200 || response.status >= 300) {
|
|
80
|
+
return yield* new ConnectStatusError({ status: response.status });
|
|
81
|
+
}
|
|
82
|
+
const page = yield* decodeBoundedResponseJson(response, FleetConnectAgentPage).pipe(Effect.mapError((cause) => new ConnectProtocolError({
|
|
83
|
+
detail: "invalid fleet agent directory page",
|
|
84
|
+
cause
|
|
85
|
+
})));
|
|
86
|
+
for (const agent of page.agents)
|
|
87
|
+
agents.push(agent);
|
|
88
|
+
for (const failure of page.failures)
|
|
89
|
+
failures.push(failure);
|
|
90
|
+
cursor = page.nextCursor;
|
|
91
|
+
} while (cursor !== null);
|
|
92
|
+
const directory = yield* Schema.decodeUnknownEffect(FleetConnectAgents)({ agents, failures }).pipe(Effect.mapError((cause) => new ConnectProtocolError({
|
|
93
|
+
detail: "invalid fleet agent directory",
|
|
94
|
+
cause
|
|
95
|
+
})));
|
|
96
|
+
yield* buildConnectForest(directory.agents).pipe(Effect.mapError((cause) => new ConnectProtocolError({
|
|
97
|
+
detail: "invalid fleet agent relationship forest",
|
|
98
|
+
cause
|
|
99
|
+
})));
|
|
100
|
+
return directory;
|
|
101
|
+
});
|
|
102
|
+
const browserRuntime = Atom.runtime(BrowserHttpClient.layerFetch);
|
|
103
|
+
export const makeConnectAtoms = () => {
|
|
104
|
+
const agents = browserRuntime.atom(loadAgents);
|
|
105
|
+
return {
|
|
106
|
+
activityFilter: Atom.make("all"),
|
|
107
|
+
agents,
|
|
108
|
+
agentsPoll: browserRuntime.atom(Atom.refresh(agents).pipe(Effect.repeat(Schedule.spaced("5 seconds")))),
|
|
109
|
+
connection: Atom.make({ _tag: "idle" }),
|
|
110
|
+
connectionRequest: Atom.make(null),
|
|
111
|
+
hostFilter: Atom.make(null),
|
|
112
|
+
preference: Atom.make(loadRememberedAgent),
|
|
113
|
+
preferenceError: Atom.make(null),
|
|
114
|
+
query: Atom.make(""),
|
|
115
|
+
selectedKey: Atom.make(null)
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
const socketUrl = (agent, cols, rows) => {
|
|
119
|
+
const url = new URL("/v1/connect/session", window.location.href);
|
|
120
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
121
|
+
url.searchParams.set("host", agent.host);
|
|
122
|
+
url.searchParams.set("agent", agent.id);
|
|
123
|
+
url.searchParams.set("cols", String(cols));
|
|
124
|
+
url.searchParams.set("rows", String(rows));
|
|
125
|
+
return url.toString();
|
|
126
|
+
};
|
|
127
|
+
const terminalWorker = (container, agent, update) => Effect.scoped(Effect.gen(function* () {
|
|
128
|
+
update({ _tag: "connecting", agent });
|
|
129
|
+
yield* Effect.tryPromise({
|
|
130
|
+
try: init,
|
|
131
|
+
catch: (cause) => new ConnectProtocolError({
|
|
132
|
+
detail: "Ghostty Web failed to initialize",
|
|
133
|
+
cause
|
|
134
|
+
})
|
|
135
|
+
});
|
|
136
|
+
const terminal = yield* acquireTerminalSetup(() => {
|
|
137
|
+
const value = new Terminal({
|
|
138
|
+
cols: 100,
|
|
139
|
+
rows: 30,
|
|
140
|
+
cursorBlink: true,
|
|
141
|
+
fontFamily: "Geist Mono, ui-monospace, monospace",
|
|
142
|
+
fontSize: 13,
|
|
143
|
+
theme: {
|
|
144
|
+
background: terminalBackground,
|
|
145
|
+
foreground: "#e7e9ec",
|
|
146
|
+
cursor: "#9dd6c5",
|
|
147
|
+
selectionBackground: "#27433c"
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
const fit = new FitAddon();
|
|
151
|
+
value.loadAddon(fit);
|
|
152
|
+
value.open(container);
|
|
153
|
+
value.blur();
|
|
154
|
+
fit.fit();
|
|
155
|
+
fit.observeResize();
|
|
156
|
+
return { fit, terminal: value };
|
|
157
|
+
}, ({ fit, terminal }) => {
|
|
158
|
+
fit.dispose();
|
|
159
|
+
terminal.dispose();
|
|
160
|
+
});
|
|
161
|
+
let ready = false;
|
|
162
|
+
let socket = null;
|
|
163
|
+
let inputOverflow = false;
|
|
164
|
+
let pendingResize = null;
|
|
165
|
+
const pendingInput = makePendingTerminalInput();
|
|
166
|
+
const send = (command) => {
|
|
167
|
+
if (socket?.readyState === WebSocket.OPEN) {
|
|
168
|
+
socket.send(JSON.stringify(command));
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
const input = terminal.terminal.onData((text) => {
|
|
172
|
+
if (ready) {
|
|
173
|
+
send({ type: "terminal.input", text });
|
|
174
|
+
}
|
|
175
|
+
else if (pendingInput.push(text) === "overflow") {
|
|
176
|
+
inputOverflow = true;
|
|
177
|
+
update({
|
|
178
|
+
_tag: "failed",
|
|
179
|
+
agent,
|
|
180
|
+
detail: "terminal input queue exceeded 64 KiB before ready"
|
|
181
|
+
});
|
|
182
|
+
socket?.close(4429, "terminal input queue limit reached");
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
const resize = terminal.terminal.onResize(({ cols, rows }) => {
|
|
186
|
+
if (!ready) {
|
|
187
|
+
pendingResize = { cols, rows };
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
send({
|
|
191
|
+
type: "terminal.resize",
|
|
192
|
+
cols,
|
|
193
|
+
rows,
|
|
194
|
+
cell_width_px: 0,
|
|
195
|
+
cell_height_px: 0
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
terminal.terminal.attachCustomWheelEventHandler((event) => {
|
|
199
|
+
const command = wheelScrollCommand(event, terminal.terminal.rows);
|
|
200
|
+
if (command === null)
|
|
201
|
+
return false;
|
|
202
|
+
if (ready)
|
|
203
|
+
send(command);
|
|
204
|
+
return true;
|
|
205
|
+
});
|
|
206
|
+
terminal.terminal.attachCustomKeyEventHandler((event) => {
|
|
207
|
+
const command = pageScrollCommand(event.key, terminal.terminal.rows);
|
|
208
|
+
if (command === null)
|
|
209
|
+
return false;
|
|
210
|
+
if (ready)
|
|
211
|
+
send(command);
|
|
212
|
+
return true;
|
|
213
|
+
});
|
|
214
|
+
const touchGesture = makeTouchScrollGesture({
|
|
215
|
+
blur: () => terminal.terminal.blur(),
|
|
216
|
+
rows: () => terminal.terminal.rows,
|
|
217
|
+
send: (command) => {
|
|
218
|
+
if (ready)
|
|
219
|
+
send(command);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
const touchStart = (event) => {
|
|
223
|
+
if (event.touches.length !== 1) {
|
|
224
|
+
touchGesture.cancel();
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const touch = event.touches.item(0);
|
|
228
|
+
if (touch === null)
|
|
229
|
+
return;
|
|
230
|
+
touchGesture.start(touch.clientY);
|
|
231
|
+
};
|
|
232
|
+
const touchMove = (event) => {
|
|
233
|
+
const touch = event.touches.item(0);
|
|
234
|
+
if (touch !== null && touchGesture.move(touch.clientY)) {
|
|
235
|
+
event.preventDefault();
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
const touchEnd = (event) => {
|
|
239
|
+
if (touchGesture.end())
|
|
240
|
+
event.preventDefault();
|
|
241
|
+
};
|
|
242
|
+
const touchCancel = () => touchGesture.cancel();
|
|
243
|
+
container.addEventListener("touchstart", touchStart, { passive: true });
|
|
244
|
+
container.addEventListener("touchmove", touchMove, { passive: false });
|
|
245
|
+
container.addEventListener("touchend", touchEnd, { passive: false });
|
|
246
|
+
container.addEventListener("touchcancel", touchCancel);
|
|
247
|
+
yield* Effect.addFinalizer(() => Effect.sync(() => {
|
|
248
|
+
pendingInput.clear();
|
|
249
|
+
input.dispose();
|
|
250
|
+
resize.dispose();
|
|
251
|
+
container.removeEventListener("touchstart", touchStart);
|
|
252
|
+
container.removeEventListener("touchmove", touchMove);
|
|
253
|
+
container.removeEventListener("touchend", touchEnd);
|
|
254
|
+
container.removeEventListener("touchcancel", touchCancel);
|
|
255
|
+
}));
|
|
256
|
+
const connectedSocket = yield* Effect.acquireRelease(Effect.callback((resume) => {
|
|
257
|
+
const value = new WebSocket(socketUrl(agent, terminal.terminal.cols, terminal.terminal.rows));
|
|
258
|
+
value.binaryType = "arraybuffer";
|
|
259
|
+
let settled = false;
|
|
260
|
+
value.addEventListener("open", () => {
|
|
261
|
+
if (settled)
|
|
262
|
+
return;
|
|
263
|
+
settled = true;
|
|
264
|
+
resume(Effect.succeed(value));
|
|
265
|
+
});
|
|
266
|
+
value.addEventListener("error", () => {
|
|
267
|
+
if (settled)
|
|
268
|
+
return;
|
|
269
|
+
settled = true;
|
|
270
|
+
resume(Effect.fail(new ConnectNetworkError({
|
|
271
|
+
detail: "terminal WebSocket failed to open"
|
|
272
|
+
})));
|
|
273
|
+
});
|
|
274
|
+
return Effect.sync(() => value.close());
|
|
275
|
+
}), (value) => Effect.sync(() => value.close(1000, "view detached")));
|
|
276
|
+
socket = connectedSocket;
|
|
277
|
+
if (inputOverflow) {
|
|
278
|
+
return yield* new ConnectInputQueueError({
|
|
279
|
+
detail: "terminal input queue exceeded 64 KiB before ready"
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
yield* Effect.callback((resume) => {
|
|
283
|
+
const message = (event) => {
|
|
284
|
+
const binary = Schema.decodeUnknownResult(Schema.instanceOf(ArrayBuffer))(event.data);
|
|
285
|
+
if (Result.isSuccess(binary)) {
|
|
286
|
+
terminal.terminal.write(new Uint8Array(binary.success));
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const decoded = Schema.decodeUnknownResult(Schema.fromJsonString(TerminalServerSignal))(event.data);
|
|
290
|
+
if (Result.isFailure(decoded)) {
|
|
291
|
+
update({
|
|
292
|
+
_tag: "failed",
|
|
293
|
+
agent,
|
|
294
|
+
detail: `invalid terminal server message: ${String(decoded.failure)}`
|
|
295
|
+
});
|
|
296
|
+
connectedSocket.close(4400, "invalid terminal server message");
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (decoded.success.type === "terminal.ready") {
|
|
300
|
+
ready = true;
|
|
301
|
+
const queued = pendingInput.drain();
|
|
302
|
+
if (queued.length > 0) {
|
|
303
|
+
send({ type: "terminal.input", text: queued });
|
|
304
|
+
}
|
|
305
|
+
if (pendingResize !== null) {
|
|
306
|
+
send({
|
|
307
|
+
type: "terminal.resize",
|
|
308
|
+
cols: pendingResize.cols,
|
|
309
|
+
rows: pendingResize.rows,
|
|
310
|
+
cell_width_px: 0,
|
|
311
|
+
cell_height_px: 0
|
|
312
|
+
});
|
|
313
|
+
pendingResize = null;
|
|
314
|
+
}
|
|
315
|
+
if (window.matchMedia("(pointer: fine)").matches) {
|
|
316
|
+
terminal.terminal.focus();
|
|
317
|
+
}
|
|
318
|
+
update({ _tag: "connected", agent });
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
const close = (event) => {
|
|
322
|
+
update(event.code === 1000
|
|
323
|
+
? { _tag: "closed", agent }
|
|
324
|
+
: {
|
|
325
|
+
_tag: "failed",
|
|
326
|
+
agent,
|
|
327
|
+
detail: event.reason || `connection closed (${event.code})`
|
|
328
|
+
});
|
|
329
|
+
resume(Effect.void);
|
|
330
|
+
};
|
|
331
|
+
connectedSocket.addEventListener("message", message);
|
|
332
|
+
connectedSocket.addEventListener("close", close, { once: true });
|
|
333
|
+
return Effect.sync(() => {
|
|
334
|
+
connectedSocket.removeEventListener("message", message);
|
|
335
|
+
connectedSocket.removeEventListener("close", close);
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
}).pipe(Effect.catch((error) => Effect.sync(() => update({ _tag: "failed", agent, detail: error.detail })))));
|
|
339
|
+
export const ConnectSurface = ({ atoms, embedded = false, roomFooter }) => {
|
|
340
|
+
const [activityFilter, setActivityFilter] = useAtom(atoms.activityFilter);
|
|
341
|
+
const directory = useAtomValue(atoms.agents);
|
|
342
|
+
const remembered = useAtomValue(atoms.preference);
|
|
343
|
+
const [connection, setConnection] = useAtom(atoms.connection);
|
|
344
|
+
const [connectionRequest, setConnectionRequest] = useAtom(atoms.connectionRequest);
|
|
345
|
+
const [hostFilter, setHostFilter] = useAtom(atoms.hostFilter);
|
|
346
|
+
const [preferenceError, setPreferenceError] = useAtom(atoms.preferenceError);
|
|
347
|
+
const [query, setQuery] = useAtom(atoms.query);
|
|
348
|
+
const [selectedKey, setSelectedKey] = useAtom(atoms.selectedKey);
|
|
349
|
+
const preferenceApplied = useRef(false);
|
|
350
|
+
const requestId = useRef(0);
|
|
351
|
+
const terminalRef = useRef(null);
|
|
352
|
+
const terminalViewportRef = useRef(null);
|
|
353
|
+
useAtomMount(atoms.agentsPoll);
|
|
354
|
+
useEffect(() => {
|
|
355
|
+
const container = terminalRef.current;
|
|
356
|
+
if (connectionRequest === null || container === null)
|
|
357
|
+
return;
|
|
358
|
+
const fiber = Effect.runFork(terminalWorker(container, connectionRequest.agent, setConnection));
|
|
359
|
+
return () => {
|
|
360
|
+
Effect.runFork(Fiber.interrupt(fiber));
|
|
361
|
+
container.replaceChildren();
|
|
362
|
+
};
|
|
363
|
+
}, [connectionRequest, setConnection]);
|
|
364
|
+
const terminalConnected = connection._tag === "connected";
|
|
365
|
+
useEffect(() => {
|
|
366
|
+
const room = terminalViewportRef.current;
|
|
367
|
+
if (!terminalConnected || room === null)
|
|
368
|
+
return;
|
|
369
|
+
return bindTerminalViewport(room, window);
|
|
370
|
+
}, [terminalConnected]);
|
|
371
|
+
const current = AsyncResult.isSuccess(directory)
|
|
372
|
+
? directory.value
|
|
373
|
+
: directory._tag === "Failure" && directory.previousSuccess._tag === "Some"
|
|
374
|
+
? directory.previousSuccess.value.value
|
|
375
|
+
: null;
|
|
376
|
+
const agents = current?.agents ?? [];
|
|
377
|
+
const selected = agents.find((agent) => connectAgentKey(agent) === selectedKey) ??
|
|
378
|
+
(connectionRequest !== null && connectAgentKey(connectionRequest.agent) === selectedKey
|
|
379
|
+
? connectionRequest.agent
|
|
380
|
+
: null);
|
|
381
|
+
const selectAgent = (agent) => {
|
|
382
|
+
preferenceApplied.current = true;
|
|
383
|
+
const key = connectAgentKey(agent);
|
|
384
|
+
setSelectedKey(key);
|
|
385
|
+
setConnection({ _tag: "connecting", agent });
|
|
386
|
+
requestId.current += 1;
|
|
387
|
+
setConnectionRequest({ agent, id: requestId.current });
|
|
388
|
+
Effect.runFork(storeRememberedAgent(key).pipe(Effect.tap(() => Effect.sync(() => setPreferenceError(null))), Effect.catch((error) => Effect.sync(() => setPreferenceError(error.operation)))));
|
|
389
|
+
};
|
|
390
|
+
useEffect(() => {
|
|
391
|
+
if (preferenceApplied.current || current === null)
|
|
392
|
+
return;
|
|
393
|
+
const stored = AsyncResult.isSuccess(remembered)
|
|
394
|
+
? { _tag: "available", key: remembered.value }
|
|
395
|
+
: { _tag: "unavailable" };
|
|
396
|
+
const fiber = Effect.runFork(resolveConnectPreferenceDecision(window.location.search, current.agents, stored).pipe(Effect.tap((decision) => Effect.sync(() => {
|
|
397
|
+
if (decision._tag === "retry") {
|
|
398
|
+
setSelectedKey(decision.key);
|
|
399
|
+
setPreferenceError(decision.error);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
preferenceApplied.current = true;
|
|
403
|
+
if (decision._tag === "select") {
|
|
404
|
+
setSelectedKey(decision.key);
|
|
405
|
+
setPreferenceError(decision.error);
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
selectAgent(decision.target);
|
|
409
|
+
}
|
|
410
|
+
}))));
|
|
411
|
+
return () => {
|
|
412
|
+
Effect.runFork(Fiber.interrupt(fiber));
|
|
413
|
+
};
|
|
414
|
+
}, [current, remembered, setPreferenceError, setSelectedKey]);
|
|
415
|
+
const moveAgentFocus = (event) => {
|
|
416
|
+
const buttons = [...event.currentTarget.querySelectorAll(".connect-agent")];
|
|
417
|
+
const currentIndex = buttons.findIndex((button) => button === event.target);
|
|
418
|
+
if (currentIndex < 0)
|
|
419
|
+
return;
|
|
420
|
+
const nextIndex = nextConnectAgentIndex(event.key, currentIndex, buttons.length);
|
|
421
|
+
if (nextIndex === null)
|
|
422
|
+
return;
|
|
423
|
+
const next = buttons.at(nextIndex);
|
|
424
|
+
if (next === undefined)
|
|
425
|
+
return;
|
|
426
|
+
event.preventDefault();
|
|
427
|
+
next.focus();
|
|
428
|
+
};
|
|
429
|
+
const disconnect = () => {
|
|
430
|
+
setConnectionRequest(null);
|
|
431
|
+
setConnection({ _tag: "idle" });
|
|
432
|
+
};
|
|
433
|
+
const directoryScreen = (_jsxs(_Fragment, { children: [embedded ? (_jsxs("header", { className: "connect-embedded-intro", children: [_jsxs("div", { children: [_jsx(Text, { variant: "meta", tone: "secondary", children: "Live fleet directory" }), _jsx(Text, { as: "h1", variant: "page-title", children: "Connect to an agent" }), _jsx(Text, { tone: "secondary", children: "Choose a worker, reviewer, or coordinator to open its exact terminal." })] }), _jsx(StateLabel, { label: current === null ? "Loading" : `${String(agents.length)} agents`, size: "compact", tone: current === null ? "neutral" : "positive" })] })) : (_jsxs("header", { className: "connect-header", children: [_jsxs("div", { children: [_jsx(Text, { variant: "meta", tone: "secondary", children: "Herdr fleet" }), _jsx(Text, { as: "h1", variant: "page-title", children: "Connect" })] }), _jsxs("nav", { className: "fleet-app-nav", "aria-label": "Fleet applications", children: [_jsx("a", { href: "/", children: "Approvals" }), _jsx("a", { href: "/connect/", "aria-current": "page", children: "Connect" })] })] })), _jsxs("section", { className: "connect-agents", "aria-label": "Herdr agents", onKeyDown: moveAgentFocus, children: [_jsxs("label", { className: "connect-search", children: [_jsx("span", { children: "Find agent" }), _jsx("input", { autoComplete: "off", id: "connect-agent-search", name: "agent-search", onChange: (event) => setQuery(event.currentTarget.value), onKeyDown: (event) => {
|
|
434
|
+
if (event.key === "Escape") {
|
|
435
|
+
event.preventDefault();
|
|
436
|
+
setQuery("");
|
|
437
|
+
event.currentTarget.blur();
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (event.key !== "ArrowDown")
|
|
441
|
+
return;
|
|
442
|
+
const firstAgent = event.currentTarget
|
|
443
|
+
.closest(".connect-agents")
|
|
444
|
+
?.querySelector(".connect-agent");
|
|
445
|
+
if (firstAgent === undefined || firstAgent === null)
|
|
446
|
+
return;
|
|
447
|
+
event.preventDefault();
|
|
448
|
+
firstAgent.focus();
|
|
449
|
+
}, placeholder: "Name, host, state\u2026", type: "search", value: query })] }), current === null ? (_jsx(Text, { tone: "secondary", children: directory._tag === "Failure" ? Cause.pretty(directory.cause) : "Loading fleet agents…" })) : agents.length === 0 ? (_jsx(Text, { tone: "secondary", children: "No live agents." })) : (_jsx(AgentDirectory, { activityFilter: activityFilter, agents: agents, hostFilter: hostFilter, onActivityFilter: setActivityFilter, onHostFilter: setHostFilter, onSelect: selectAgent, query: query, selectedKey: selectedKey })), connection._tag === "connecting" ? (_jsxs("small", { className: "connect-status-message", children: ["Connecting to ", connection.agent.name, "\u2026"] })) : connection._tag === "failed" ? (_jsxs("small", { className: "connect-status-message", "data-tone": "critical", children: [connection.agent.name, " \u00B7 ", connection.detail] })) : connection._tag === "closed" ? (_jsxs("small", { className: "connect-status-message", children: [connection.agent.name, " disconnected."] })) : null, remembered._tag === "Failure" ? (_jsxs("small", { className: "connect-preference-error", children: ["Selection memory unavailable \u00B7 ", Cause.pretty(remembered.cause)] })) : preferenceError === null ? null : (_jsxs("small", { className: "connect-preference-error", children: ["Selection memory unavailable \u00B7 ", preferenceError] })), (current?.failures.length ?? 0) === 0 ? null : (_jsx("div", { className: "connect-failures", children: current?.failures.map((failure) => (_jsxs("small", { children: [failure.host, " \u00B7 ", failure.reason.replaceAll("_", " ")] }, failure.host))) }))] })] }));
|
|
450
|
+
const terminalScreen = (_jsxs(Surface, { as: "section", padding: "none", className: "terminal-stage", children: [_jsxs("div", { className: "terminal-bar", children: [_jsx("button", { className: "terminal-back", onClick: disconnect, type: "button", children: "Agents" }), _jsxs("div", { children: [_jsx("strong", { children: selected?.name ?? "Agent" }), _jsx("small", { children: selected === null ? "Herdr terminal" : `${selected.host} · ${selected.kind}` })] }), _jsx(StateLabel, { label: "connected", tone: "positive", size: "compact" })] }), _jsx("div", { "aria-label": selected === null ? "Agent terminal" : `${selected.name} terminal`, className: "ghostty-terminal", ref: terminalRef })] }));
|
|
451
|
+
return (_jsxs("div", { className: embedded ? "connect-shell connect-shell-embedded" : "connect-shell", children: [_jsx(ConnectWorkspace, { directory: directoryScreen, mode: connection._tag === "connected" ? "terminal" : "directory", terminal: terminalScreen, terminalViewportRef: terminalViewportRef }), roomFooter] }));
|
|
452
|
+
};
|
|
453
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACvE,OAAO,KAAK,WAAW,MAAM,wCAAwC,CAAA;AACrE,OAAO,KAAK,IAAI,MAAM,iCAAiC,CAAA;AACvD,OAAO,KAAK,UAAU,MAAM,iCAAiC,CAAA;AAE7D,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAsC,MAAM,OAAO,CAAA;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAGL,qBAAqB,EACrB,kBAAkB,EAElB,oBAAoB,EACrB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAA4B,MAAM,WAAW,CAAA;AACvG,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAoC,gCAAgC,EAAE,MAAM,aAAa,CAAA;AAChG,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAErD,MAAM,mBAAoB,SAAQ,MAAM,CAAC,WAAW,EAAuB,CAAC,qBAAqB,EAAE;IACjG,MAAM,EAAE,MAAM,CAAC,MAAM;CACtB,CAAC;CAAG;AAEL,MAAM,kBAAmB,SAAQ,MAAM,CAAC,WAAW,EAAsB,CAAC,oBAAoB,EAAE;IAC9F,MAAM,EAAE,MAAM,CAAC,MAAM;CACtB,CAAC;CAAG;AAEL,MAAM,oBAAqB,SAAQ,MAAM,CAAC,WAAW,EAAwB,CAAC,sBAAsB,EAAE;IACpG,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;CACvB,CAAC;CAAG;AAEL,MAAM,sBAAuB,SAAQ,MAAM,CAAC,WAAW,EAA0B,CAAC,wBAAwB,EAAE;IAC1G,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;CACvB,CAAC;CAAG;AAEL,MAAM,sBAAuB,SAAQ,MAAM,CAAC,WAAW,EAA0B,CAAC,wBAAwB,EAAE;IAC1G,MAAM,EAAE,MAAM,CAAC,MAAM;CACtB,CAAC;CAAG;AAkBL,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;AAC9F,MAAM,yBAAyB,GAAG,qBAAqB,CAAA;AAEvD,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAC;IACrC,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,yBAAyB,CAAC;IACjE,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,sBAAsB,CAAC;QACzB,SAAS,EAAE,oBAAoB;QAC/B,KAAK;KACN,CAAC;CACL,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACvB,KAAK,KAAK,IAAI;IACZ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;IACtB,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CACxD,MAAM,CAAC,QAAQ,CACb,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,sBAAsB,CAAC;QACzB,SAAS,EAAE,sBAAsB;QACjC,KAAK;KACN,CAAC,CACL,CACF,CACN,CACF,CAAA;AAED,MAAM,oBAAoB,GAAG,CAAC,GAAW,EAAE,EAAE,CAC3C,MAAM,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CACtD,MAAM,CAAC,QAAQ,CACb,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,sBAAsB,CAAC;IACzB,SAAS,EAAE,sBAAsB;IACjC,KAAK;CACN,CAAC,CACL,EACD,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACvB,MAAM,CAAC,GAAG,CAAC;IACT,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,yBAAyB,EAAE,KAAK,CAAC;IACxE,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,sBAAsB,CAAC;QACzB,SAAS,EAAE,qBAAqB;QAChC,KAAK;KACN,CAAC;CACL,CAAC,CACH,CACF,CAAA;AAEH,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACrC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAA;IAC3C,MAAM,MAAM,GAAwB,EAAE,CAAA;IACtC,MAAM,QAAQ,GAAgE,EAAE,CAAA;IAChF,IAAI,MAAM,GAA8B,IAAI,CAAA;IAC5C,GAAG,CAAC;QACF,MAAM,IAAI,GACR,MAAM,KAAK,IAAI;YACb,CAAC,CAAC,oBAAoB;YACtB,CAAC,CAAC,iCAAiC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAA;QAClH,MAAM,QAAQ,GAA0C,KAAK,CAAC,CAAC,MAAM;aAClE,GAAG,CAAC,IAAI,CAAC;aACT,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,mBAAmB,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACvF,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YACpD,OAAO,KAAK,CAAC,CAAC,IAAI,kBAAkB,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;QACnE,CAAC;QACD,MAAM,IAAI,GAAsC,KAAK,CAAC,CAAC,yBAAyB,CAC9E,QAAQ,EACR,qBAAqB,CACtB,CAAC,IAAI,CACJ,MAAM,CAAC,QAAQ,CACb,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,oBAAoB,CAAC;YACvB,MAAM,EAAE,oCAAoC;YAC5C,KAAK;SACN,CAAC,CACL,CACF,CAAA;QACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACnD,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ;YAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC3D,MAAM,GAAG,IAAI,CAAC,UAAU,CAAA;IAC1B,CAAC,QAAQ,MAAM,KAAK,IAAI,EAAC;IACzB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAChG,MAAM,CAAC,QAAQ,CACb,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,oBAAoB,CAAC;QACvB,MAAM,EAAE,+BAA+B;QACvC,KAAK;KACN,CAAC,CACL,CACF,CAAA;IACD,KAAK,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,CAC9C,MAAM,CAAC,QAAQ,CACb,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,oBAAoB,CAAC;QACvB,MAAM,EAAE,yCAAyC;QACjD,KAAK;KACN,CAAC,CACL,CACF,CAAA;IACD,OAAO,SAAS,CAAA;AAClB,CAAC,CAAC,CAAA;AAEF,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAA;AAEjE,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE;IACnC,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC9C,OAAO;QACL,cAAc,EAAE,IAAI,CAAC,IAAI,CAAsB,KAAK,CAAC;QACrD,MAAM;QACN,UAAU,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACvG,UAAU,EAAE,IAAI,CAAC,IAAI,CAAkB,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACxD,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAA2B,IAAI,CAAC;QAC5D,UAAU,EAAE,IAAI,CAAC,IAAI,CAAgB,IAAI,CAAC;QAC1C,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC;QAC1C,eAAe,EAAE,IAAI,CAAC,IAAI,CAAgB,IAAI,CAAC;QAC/C,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpB,WAAW,EAAE,IAAI,CAAC,IAAI,CAAgB,IAAI,CAAC;KAC5C,CAAA;AACH,CAAC,CAAA;AAID,MAAM,SAAS,GAAG,CAAC,KAAmB,EAAE,IAAY,EAAE,IAAY,EAAU,EAAE;IAC5E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAChE,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;IACzD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;IACxC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;IACvC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1C,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,cAAc,GAAG,CAAC,SAAsB,EAAE,KAAmB,EAAE,MAAwC,EAAE,EAAE,CAC/G,MAAM,CAAC,MAAM,CACX,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAA;IACrC,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;QACvB,GAAG,EAAE,IAAI;QACT,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,oBAAoB,CAAC;YACvB,MAAM,EAAE,kCAAkC;YAC1C,KAAK;SACN,CAAC;KACL,CAAC,CAAA;IACF,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAC1C,GAAG,EAAE;QACH,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC;YACzB,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,EAAE;YACR,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,qCAAqC;YACjD,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE;gBACL,UAAU,EAAE,kBAAkB;gBAC9B,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE,SAAS;gBACjB,mBAAmB,EAAE,SAAS;aAC/B;SACF,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,IAAI,QAAQ,EAAE,CAAA;QAC1B,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QACpB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACrB,KAAK,CAAC,IAAI,EAAE,CAAA;QACZ,GAAG,CAAC,GAAG,EAAE,CAAA;QACT,GAAG,CAAC,aAAa,EAAE,CAAA;QACnB,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;IACjC,CAAC,EACD,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE;QACpB,GAAG,CAAC,OAAO,EAAE,CAAA;QACb,QAAQ,CAAC,OAAO,EAAE,CAAA;IACpB,CAAC,CACF,CAAA;IACD,IAAI,KAAK,GAAG,KAAK,CAAA;IACjB,IAAI,MAAM,GAAqB,IAAI,CAAA;IACnC,IAAI,aAAa,GAAG,KAAK,CAAA;IACzB,IAAI,aAAa,GAGN,IAAI,CAAA;IACf,MAAM,YAAY,GAAG,wBAAwB,EAAE,CAAA;IAC/C,MAAM,IAAI,GAAG,CAAC,OAA8B,EAAQ,EAAE;QACpD,IAAI,MAAM,EAAE,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YAC1C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;QACtC,CAAC;IACH,CAAC,CAAA;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC9C,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAA;QACxC,CAAC;aAAM,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;YAClD,aAAa,GAAG,IAAI,CAAA;YACpB,MAAM,CAAC;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK;gBACL,MAAM,EAAE,mDAAmD;aAC5D,CAAC,CAAA;YACF,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,oCAAoC,CAAC,CAAA;QAC3D,CAAC;IACH,CAAC,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;QAC3D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,aAAa,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;YAC9B,OAAM;QACR,CAAC;QACD,IAAI,CAAC;YACH,IAAI,EAAE,iBAAiB;YACvB,IAAI;YACJ,IAAI;YACJ,aAAa,EAAE,CAAC;YAChB,cAAc,EAAE,CAAC;SAClB,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IACF,QAAQ,CAAC,QAAQ,CAAC,6BAA6B,CAAC,CAAC,KAAK,EAAE,EAAE;QACxD,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACjE,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,KAAK,CAAA;QAClC,IAAI,KAAK;YAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QACxB,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CAAA;IACF,QAAQ,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC,KAAK,EAAE,EAAE;QACtD,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACpE,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,KAAK,CAAA;QAClC,IAAI,KAAK;YAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QACxB,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CAAA;IACF,MAAM,YAAY,GAAG,sBAAsB,CAAC;QAC1C,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE;QACpC,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI;QAClC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YAChB,IAAI,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QAC1B,CAAC;KACF,CAAC,CAAA;IACF,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAQ,EAAE;QAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,YAAY,CAAC,MAAM,EAAE,CAAA;YACrB,OAAM;QACR,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACnC,IAAI,KAAK,KAAK,IAAI;YAAE,OAAM;QAC1B,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACnC,CAAC,CAAA;IACD,MAAM,SAAS,GAAG,CAAC,KAAiB,EAAQ,EAAE;QAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACnC,IAAI,KAAK,KAAK,IAAI,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACvD,KAAK,CAAC,cAAc,EAAE,CAAA;QACxB,CAAC;IACH,CAAC,CAAA;IACD,MAAM,QAAQ,GAAG,CAAC,KAAiB,EAAQ,EAAE;QAC3C,IAAI,YAAY,CAAC,GAAG,EAAE;YAAE,KAAK,CAAC,cAAc,EAAE,CAAA;IAChD,CAAC,CAAA;IACD,MAAM,WAAW,GAAG,GAAS,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAA;IACrD,SAAS,CAAC,gBAAgB,CAAC,YAAY,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IACvE,SAAS,CAAC,gBAAgB,CAAC,WAAW,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;IACtE,SAAS,CAAC,gBAAgB,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;IACpE,SAAS,CAAC,gBAAgB,CAAC,aAAa,EAAE,WAAW,CAAC,CAAA;IACtD,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QACf,YAAY,CAAC,KAAK,EAAE,CAAA;QACpB,KAAK,CAAC,OAAO,EAAE,CAAA;QACf,MAAM,CAAC,OAAO,EAAE,CAAA;QAChB,SAAS,CAAC,mBAAmB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;QACvD,SAAS,CAAC,mBAAmB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;QACrD,SAAS,CAAC,mBAAmB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;QACnD,SAAS,CAAC,mBAAmB,CAAC,aAAa,EAAE,WAAW,CAAC,CAAA;IAC3D,CAAC,CAAC,CACH,CAAA;IACD,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAClD,MAAM,CAAC,QAAQ,CAAiC,CAAC,MAAM,EAAE,EAAE;QACzD,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAA;QAC7F,KAAK,CAAC,UAAU,GAAG,aAAa,CAAA;QAChC,IAAI,OAAO,GAAG,KAAK,CAAA;QACnB,KAAK,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;YAClC,IAAI,OAAO;gBAAE,OAAM;YACnB,OAAO,GAAG,IAAI,CAAA;YACd,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;QAC/B,CAAC,CAAC,CAAA;QACF,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YACnC,IAAI,OAAO;gBAAE,OAAM;YACnB,OAAO,GAAG,IAAI,CAAA;YACd,MAAM,CACJ,MAAM,CAAC,IAAI,CACT,IAAI,mBAAmB,CAAC;gBACtB,MAAM,EAAE,mCAAmC;aAC5C,CAAC,CACH,CACF,CAAA;QACH,CAAC,CAAC,CAAA;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;IACzC,CAAC,CAAC,EACF,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CACjE,CAAA;IACD,MAAM,GAAG,eAAe,CAAA;IACxB,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC,CAAC,IAAI,sBAAsB,CAAC;YACvC,MAAM,EAAE,mDAAmD;SAC5D,CAAC,CAAA;IACJ,CAAC;IACD,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAA4B,CAAC,MAAM,EAAE,EAAE;QAC3D,MAAM,OAAO,GAAG,CAAC,KAAyC,EAAQ,EAAE;YAClE,MAAM,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACrF,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7B,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;gBACvD,OAAM;YACR,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACnG,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC;oBACL,IAAI,EAAE,QAAQ;oBACd,KAAK;oBACL,MAAM,EAAE,oCAAoC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;iBACtE,CAAC,CAAA;gBACF,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,iCAAiC,CAAC,CAAA;gBAC9D,OAAM;YACR,CAAC;YACD,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBAC9C,KAAK,GAAG,IAAI,CAAA;gBACZ,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,CAAA;gBACnC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;gBAChD,CAAC;gBACD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;oBAC3B,IAAI,CAAC;wBACH,IAAI,EAAE,iBAAiB;wBACvB,IAAI,EAAE,aAAa,CAAC,IAAI;wBACxB,IAAI,EAAE,aAAa,CAAC,IAAI;wBACxB,aAAa,EAAE,CAAC;wBAChB,cAAc,EAAE,CAAC;qBAClB,CAAC,CAAA;oBACF,aAAa,GAAG,IAAI,CAAA;gBACtB,CAAC;gBACD,IAAI,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE,CAAC;oBACjD,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;gBAC3B,CAAC;gBACD,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAA;YACtC,CAAC;QACH,CAAC,CAAA;QACD,MAAM,KAAK,GAAG,CAAC,KAAiB,EAAQ,EAAE;YACxC,MAAM,CACJ,KAAK,CAAC,IAAI,KAAK,IAAI;gBACjB,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE;gBAC3B,CAAC,CAAC;oBACE,IAAI,EAAE,QAAQ;oBACd,KAAK;oBACL,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,sBAAsB,KAAK,CAAC,IAAI,GAAG;iBAC5D,CACN,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACrB,CAAC,CAAA;QACD,eAAe,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QACpD,eAAe,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAChE,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACtB,eAAe,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;YACvD,eAAe,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACrD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAC7G,CAAA;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAC7B,KAAK,EACL,QAAQ,GAAG,KAAK,EAChB,UAAU,EAKX,EAAE,EAAE;IACH,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;IACzE,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAC5C,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IACjD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IAC7D,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;IAClF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IAC7D,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;IAC5E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC9C,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IAChE,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IACvC,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;IAC3B,MAAM,WAAW,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IAChD,MAAM,mBAAmB,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IACxD,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IAE9B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAA;QACrC,IAAI,iBAAiB,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI;YAAE,OAAM;QAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAA;QAC/F,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;YACtC,SAAS,CAAC,eAAe,EAAE,CAAA;QAC7B,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC,CAAA;IAEtC,MAAM,iBAAiB,GAAG,UAAU,CAAC,IAAI,KAAK,WAAW,CAAA;IACzD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAA;QACxC,IAAI,CAAC,iBAAiB,IAAI,IAAI,KAAK,IAAI;YAAE,OAAM;QAC/C,OAAO,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC3C,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAEvB,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,CAAC,SAAS,CAAC;QAC9C,CAAC,CAAC,SAAS,CAAC,KAAK;QACjB,CAAC,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS,IAAI,SAAS,CAAC,eAAe,CAAC,IAAI,KAAK,MAAM;YACzE,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK;YACvC,CAAC,CAAC,IAAI,CAAA;IACV,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,EAAE,CAAA;IACpC,MAAM,QAAQ,GACZ,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,WAAW,CAAC;QAC9D,CAAC,iBAAiB,KAAK,IAAI,IAAI,eAAe,CAAC,iBAAiB,CAAC,KAAK,CAAC,KAAK,WAAW;YACrF,CAAC,CAAC,iBAAiB,CAAC,KAAK;YACzB,CAAC,CAAC,IAAI,CAAC,CAAA;IACX,MAAM,WAAW,GAAG,CAAC,KAAmB,EAAQ,EAAE;QAChD,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;QAChC,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;QAClC,cAAc,CAAC,GAAG,CAAC,CAAA;QACnB,aAAa,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAA;QAC5C,SAAS,CAAC,OAAO,IAAI,CAAC,CAAA;QACtB,oBAAoB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAA;QACtD,MAAM,CAAC,OAAO,CACZ,oBAAoB,CAAC,GAAG,CAAC,CAAC,IAAI,CAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAC7D,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAChF,CACF,CAAA;IACH,CAAC,CAAA;IACD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,iBAAiB,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI;YAAE,OAAM;QACzD,MAAM,MAAM,GAAgC,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC;YAC3E,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,UAAU,CAAC,KAAK,EAAE;YAC9C,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;QAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAC1B,gCAAgC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,IAAI,CACnF,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CACtB,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACf,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC9B,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;gBAC5B,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;gBAClC,OAAM;YACR,CAAC;YACD,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;YAChC,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC/B,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;gBAC5B,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACpC,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC,CAAC,CACH,CACF,CACF,CAAA;QACD,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;QACxC,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,cAAc,CAAC,CAAC,CAAA;IAC7D,MAAM,cAAc,GAAG,CAAC,KAAiC,EAAQ,EAAE;QACjE,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAoB,gBAAgB,CAAC,CAAC,CAAA;QAC9F,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC,CAAA;QAC3E,IAAI,YAAY,GAAG,CAAC;YAAE,OAAM;QAC5B,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;QAChF,IAAI,SAAS,KAAK,IAAI;YAAE,OAAM;QAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,CAAA;QAClC,IAAI,IAAI,KAAK,SAAS;YAAE,OAAM;QAC9B,KAAK,CAAC,cAAc,EAAE,CAAA;QACtB,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC,CAAA;IAED,MAAM,UAAU,GAAG,GAAS,EAAE;QAC5B,oBAAoB,CAAC,IAAI,CAAC,CAAA;QAC1B,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;IACjC,CAAC,CAAA;IAED,MAAM,eAAe,GAAG,CACtB,8BACG,QAAQ,CAAC,CAAC,CAAC,CACV,kBAAQ,SAAS,EAAC,wBAAwB,aACxC,0BACE,KAAC,IAAI,IAAC,OAAO,EAAC,MAAM,EAAC,IAAI,EAAC,WAAW,qCAE9B,EACP,KAAC,IAAI,IAAC,EAAE,EAAC,IAAI,EAAC,OAAO,EAAC,YAAY,oCAE3B,EACP,KAAC,IAAI,IAAC,IAAI,EAAC,WAAW,sFAA6E,IAC/F,EACN,KAAC,UAAU,IACT,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EACvE,IAAI,EAAC,SAAS,EACd,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,GAC/C,IACK,CACV,CAAC,CAAC,CAAC,CACF,kBAAQ,SAAS,EAAC,gBAAgB,aAChC,0BACE,KAAC,IAAI,IAAC,OAAO,EAAC,MAAM,EAAC,IAAI,EAAC,WAAW,4BAE9B,EACP,KAAC,IAAI,IAAC,EAAE,EAAC,IAAI,EAAC,OAAO,EAAC,YAAY,wBAE3B,IACH,EACN,eAAK,SAAS,EAAC,eAAe,gBAAY,oBAAoB,aAC5D,YAAG,IAAI,EAAC,GAAG,0BAAc,EACzB,YAAG,IAAI,EAAC,WAAW,kBAAc,MAAM,wBAEnC,IACA,IACC,CACV,EACD,mBAAS,SAAS,EAAC,gBAAgB,gBAAY,cAAc,EAAC,SAAS,EAAE,cAAc,aACrF,iBAAO,SAAS,EAAC,gBAAgB,aAC/B,wCAAuB,EACvB,gBACE,YAAY,EAAC,KAAK,EAClB,EAAE,EAAC,sBAAsB,EACzB,IAAI,EAAC,cAAc,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,EACxD,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;oCACnB,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;wCAC3B,KAAK,CAAC,cAAc,EAAE,CAAA;wCACtB,QAAQ,CAAC,EAAE,CAAC,CAAA;wCACZ,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,CAAA;wCAC1B,OAAM;oCACR,CAAC;oCACD,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW;wCAAE,OAAM;oCACrC,MAAM,UAAU,GAAG,KAAK,CAAC,aAAa;yCACnC,OAAO,CAAC,iBAAiB,CAAC;wCAC3B,EAAE,aAAa,CAAoB,gBAAgB,CAAC,CAAA;oCACtD,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,IAAI;wCAAE,OAAM;oCAC3D,KAAK,CAAC,cAAc,EAAE,CAAA;oCACtB,UAAU,CAAC,KAAK,EAAE,CAAA;gCACpB,CAAC,EACD,WAAW,EAAC,yBAAoB,EAChC,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,KAAK,GACZ,IACI,EACP,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAClB,KAAC,IAAI,IAAC,IAAI,EAAC,WAAW,YACnB,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,uBAAuB,GAClF,CACR,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACxB,KAAC,IAAI,IAAC,IAAI,EAAC,WAAW,gCAAuB,CAC9C,CAAC,CAAC,CAAC,CACF,KAAC,cAAc,IACb,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,gBAAgB,EAAE,iBAAiB,EACnC,YAAY,EAAE,aAAa,EAC3B,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,WAAW,GACxB,CACH,EACA,UAAU,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,CAClC,iBAAO,SAAS,EAAC,wBAAwB,+BAAgB,UAAU,CAAC,KAAK,CAAC,IAAI,cAAU,CACzF,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CACjC,iBAAO,SAAS,EAAC,wBAAwB,eAAW,UAAU,aAC3D,UAAU,CAAC,KAAK,CAAC,IAAI,cAAK,UAAU,CAAC,MAAM,IACtC,CACT,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CACjC,iBAAO,SAAS,EAAC,wBAAwB,aAAE,UAAU,CAAC,KAAK,CAAC,IAAI,sBAAuB,CACxF,CAAC,CAAC,CAAC,IAAI,EACP,UAAU,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAC/B,iBAAO,SAAS,EAAC,0BAA0B,qDACT,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IACxD,CACT,CAAC,CAAC,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACpC,iBAAO,SAAS,EAAC,0BAA0B,qDAAiC,eAAe,IAAS,CACrG,EACA,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC9C,cAAK,SAAS,EAAC,kBAAkB,YAC9B,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAClC,4BACG,OAAO,CAAC,IAAI,cAAK,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,KAD3C,OAAO,CAAC,IAAI,CAEhB,CACT,CAAC,GACE,CACP,IACO,IACT,CACJ,CAAA;IAED,MAAM,cAAc,GAAG,CACrB,MAAC,OAAO,IAAC,EAAE,EAAC,SAAS,EAAC,OAAO,EAAC,MAAM,EAAC,SAAS,EAAC,gBAAgB,aAC7D,eAAK,SAAS,EAAC,cAAc,aAC3B,iBAAQ,SAAS,EAAC,eAAe,EAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAC,QAAQ,uBAE3D,EACT,0BACE,2BAAS,QAAQ,EAAE,IAAI,IAAI,OAAO,GAAU,EAC5C,0BAAQ,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,GAAS,IACzF,EACN,KAAC,UAAU,IAAC,KAAK,EAAC,WAAW,EAAC,IAAI,EAAC,UAAU,EAAC,IAAI,EAAC,SAAS,GAAG,IAC3D,EACN,4BACc,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,WAAW,EAC9E,SAAS,EAAC,kBAAkB,EAC5B,GAAG,EAAE,WAAW,GAChB,IACM,CACX,CAAA;IAED,OAAO,CACL,eAAK,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,sCAAsC,CAAC,CAAC,CAAC,eAAe,aACjF,KAAC,gBAAgB,IACf,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,UAAU,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,EAChE,QAAQ,EAAE,cAAc,EACxB,mBAAmB,EAAE,mBAAmB,GACxC,EACD,UAAU,IACP,CACP,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { AgentInventory, AgentWorkerObservation, FleetOperationError, FleetStoreError } from "@knpkv/herdr-fleet";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
4
|
+
import type { AgentActivityStore } from "./activity-store.js";
|
|
5
|
+
import { ConnectPeerError } from "./errors.js";
|
|
6
|
+
import type { AgentRelationshipStore } from "./relationship-store.js";
|
|
7
|
+
export interface AgentSource {
|
|
8
|
+
readonly agents: () => Effect.Effect<AgentInventory, FleetOperationError>;
|
|
9
|
+
readonly workers: () => Effect.Effect<ReadonlyArray<AgentWorkerObservation>, FleetStoreError>;
|
|
10
|
+
}
|
|
11
|
+
export interface ConnectPeerTarget {
|
|
12
|
+
readonly agentsUrl: string | null;
|
|
13
|
+
readonly host: string;
|
|
14
|
+
readonly online: boolean;
|
|
15
|
+
readonly terminalUrl: string | null;
|
|
16
|
+
}
|
|
17
|
+
export declare const pageFleetConnectAgents: (directory: {
|
|
18
|
+
readonly agents: readonly {
|
|
19
|
+
readonly id: string;
|
|
20
|
+
readonly host: string;
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly kind: string;
|
|
23
|
+
readonly state: string;
|
|
24
|
+
readonly work: string;
|
|
25
|
+
readonly lastActivityAt: number;
|
|
26
|
+
readonly relationship?: {
|
|
27
|
+
readonly parentAgentId: string;
|
|
28
|
+
readonly relation: "delegated" | "pair" | "review";
|
|
29
|
+
};
|
|
30
|
+
}[];
|
|
31
|
+
readonly failures: readonly {
|
|
32
|
+
readonly host: string;
|
|
33
|
+
readonly reason: "invalid_response" | "offline" | "request_failed" | "timeout" | "unavailable";
|
|
34
|
+
}[];
|
|
35
|
+
}, cursor: {
|
|
36
|
+
readonly host: string;
|
|
37
|
+
readonly id: string;
|
|
38
|
+
} | null) => Effect.Effect<{
|
|
39
|
+
readonly agents: readonly {
|
|
40
|
+
readonly id: string;
|
|
41
|
+
readonly host: string;
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly kind: string;
|
|
44
|
+
readonly state: string;
|
|
45
|
+
readonly work: string;
|
|
46
|
+
readonly lastActivityAt: number;
|
|
47
|
+
readonly relationship?: {
|
|
48
|
+
readonly parentAgentId: string;
|
|
49
|
+
readonly relation: "delegated" | "pair" | "review";
|
|
50
|
+
};
|
|
51
|
+
}[];
|
|
52
|
+
readonly failures: readonly {
|
|
53
|
+
readonly host: string;
|
|
54
|
+
readonly reason: "invalid_response" | "offline" | "request_failed" | "timeout" | "unavailable";
|
|
55
|
+
}[];
|
|
56
|
+
readonly nextCursor: {
|
|
57
|
+
readonly host: string;
|
|
58
|
+
readonly id: string;
|
|
59
|
+
} | null;
|
|
60
|
+
}, ConnectPeerError, never>;
|
|
61
|
+
export declare const localConnectAgents: (config: {
|
|
62
|
+
readonly host: string;
|
|
63
|
+
readonly repository: string;
|
|
64
|
+
readonly stateDirectory: string;
|
|
65
|
+
readonly crossHost: boolean;
|
|
66
|
+
readonly port: number;
|
|
67
|
+
readonly localPort: number;
|
|
68
|
+
readonly approvalPort: number;
|
|
69
|
+
readonly allowedUsers: readonly string[];
|
|
70
|
+
readonly approvalNodes: readonly string[];
|
|
71
|
+
readonly machines: readonly {
|
|
72
|
+
readonly host: string;
|
|
73
|
+
readonly nodeId: string;
|
|
74
|
+
}[];
|
|
75
|
+
readonly applyMachines: readonly string[];
|
|
76
|
+
readonly checkCommand: readonly string[];
|
|
77
|
+
readonly applyCommand: readonly string[] | null;
|
|
78
|
+
readonly browserMcpRecoverCommand: readonly string[] | null;
|
|
79
|
+
readonly coordinatorCommand: readonly string[];
|
|
80
|
+
readonly herdrCommand: string;
|
|
81
|
+
readonly tailscaleCommand: string;
|
|
82
|
+
readonly approvalTls: {
|
|
83
|
+
readonly certificatePath: string;
|
|
84
|
+
readonly privateKeyPath: string;
|
|
85
|
+
} | null;
|
|
86
|
+
readonly approvalHub: {
|
|
87
|
+
readonly host: string;
|
|
88
|
+
readonly nodeId: string;
|
|
89
|
+
readonly url: string;
|
|
90
|
+
};
|
|
91
|
+
readonly pushAllowedOrigins: readonly string[];
|
|
92
|
+
readonly pushSubject: string;
|
|
93
|
+
}, source: AgentSource, store: AgentActivityStore, relationshipStore: AgentRelationshipStore, observedAt: number) => Effect.Effect<{
|
|
94
|
+
readonly host: string;
|
|
95
|
+
readonly agents: readonly {
|
|
96
|
+
readonly id: string;
|
|
97
|
+
readonly host: string;
|
|
98
|
+
readonly name: string;
|
|
99
|
+
readonly kind: string;
|
|
100
|
+
readonly state: string;
|
|
101
|
+
readonly work: string;
|
|
102
|
+
readonly lastActivityAt: number;
|
|
103
|
+
readonly relationship?: {
|
|
104
|
+
readonly parentAgentId: string;
|
|
105
|
+
readonly relation: "delegated" | "pair" | "review";
|
|
106
|
+
};
|
|
107
|
+
}[];
|
|
108
|
+
}, ConnectPeerError, import("effect/Crypto").Crypto>;
|
|
109
|
+
export declare const fetchPeerConnectAgents: (peer: ConnectPeerTarget) => Effect.Effect<{
|
|
110
|
+
readonly host: string;
|
|
111
|
+
readonly agents: readonly {
|
|
112
|
+
readonly id: string;
|
|
113
|
+
readonly host: string;
|
|
114
|
+
readonly name: string;
|
|
115
|
+
readonly kind: string;
|
|
116
|
+
readonly state: string;
|
|
117
|
+
readonly work: string;
|
|
118
|
+
readonly lastActivityAt: number;
|
|
119
|
+
readonly relationship?: {
|
|
120
|
+
readonly parentAgentId: string;
|
|
121
|
+
readonly relation: "delegated" | "pair" | "review";
|
|
122
|
+
};
|
|
123
|
+
}[];
|
|
124
|
+
}, ConnectPeerError, HttpClient.HttpClient>;
|
|
125
|
+
export declare const fleetConnectAgents: (local: Effect.Effect<{
|
|
126
|
+
readonly host: string;
|
|
127
|
+
readonly agents: readonly {
|
|
128
|
+
readonly id: string;
|
|
129
|
+
readonly host: string;
|
|
130
|
+
readonly name: string;
|
|
131
|
+
readonly kind: string;
|
|
132
|
+
readonly state: string;
|
|
133
|
+
readonly work: string;
|
|
134
|
+
readonly lastActivityAt: number;
|
|
135
|
+
readonly relationship?: {
|
|
136
|
+
readonly parentAgentId: string;
|
|
137
|
+
readonly relation: "delegated" | "pair" | "review";
|
|
138
|
+
};
|
|
139
|
+
}[];
|
|
140
|
+
}, ConnectPeerError, never>, peers: readonly ConnectPeerTarget[]) => Effect.Effect<{
|
|
141
|
+
readonly agents: readonly {
|
|
142
|
+
readonly id: string;
|
|
143
|
+
readonly host: string;
|
|
144
|
+
readonly name: string;
|
|
145
|
+
readonly kind: string;
|
|
146
|
+
readonly state: string;
|
|
147
|
+
readonly work: string;
|
|
148
|
+
readonly lastActivityAt: number;
|
|
149
|
+
readonly relationship?: {
|
|
150
|
+
readonly parentAgentId: string;
|
|
151
|
+
readonly relation: "delegated" | "pair" | "review";
|
|
152
|
+
};
|
|
153
|
+
}[];
|
|
154
|
+
readonly failures: readonly {
|
|
155
|
+
readonly host: string;
|
|
156
|
+
readonly reason: "invalid_response" | "offline" | "request_failed" | "timeout" | "unavailable";
|
|
157
|
+
}[];
|
|
158
|
+
}, ConnectPeerError, HttpClient.HttpClient>;
|
|
159
|
+
//# sourceMappingURL=directory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory.d.ts","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EAEhB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAAE,MAAM,EAAkB,MAAM,QAAQ,CAAA;AAC/C,OAAO,KAAK,UAAU,MAAM,iCAAiC,CAAA;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAa9C,OAAO,KAAK,EAAE,sBAAsB,EAA2B,MAAM,yBAAyB,CAAA;AAE9F,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAA;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,sBAAsB,CAAC,EAAE,eAAe,CAAC,CAAA;CAC9F;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CACpC;AASD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BA0BjC,CAAA;AAEF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oDAmH7B,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;2CAsDlC,CAAA;AAED,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CAkC7B,CAAA"}
|