@amd-gaia/gaia 0.1.0 → 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.
@@ -0,0 +1,613 @@
1
+ // Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
2
+ // SPDX-License-Identifier: MIT
3
+ /**
4
+ * Process lifecycle for the two binaries this package installs.
5
+ *
6
+ * **Sidecar** — locate the frozen binary, spawn it, poll `GET /health`, check the
7
+ * contract version via `GET /version`, and shut it down killing the whole process
8
+ * tree. Tree-kill matters: a PyInstaller one-file build spawns a child uvicorn
9
+ * process that `child.kill()` on the parent does NOT reap, leaving the port held.
10
+ *
11
+ * **TUI** — exec it with stdio inherited and propagate its exit code, so the
12
+ * terminal UI owns the terminal completely.
13
+ *
14
+ * Note on who spawns the sidecar in the normal `gaia` flow: the GAIA daemon does.
15
+ * The TUI reaches agents through the daemon's relay and deliberately never holds a
16
+ * sidecar bearer token, so `gaia run` stages the *verified* sidecar binary into the
17
+ * daemon's cache and lets the daemon own its process. The helpers below are the
18
+ * direct path — used by `gaia serve` and by programmatic integrators who want the
19
+ * REST surface without a daemon.
20
+ */
21
+ import { spawn, spawnSync } from "node:child_process";
22
+ import crypto from "node:crypto";
23
+ import fs from "node:fs";
24
+ import net from "node:net";
25
+ import path from "node:path";
26
+ import { BinaryNotFoundError, HealthTimeoutError, HttpError, IntegrityError, MalformedResponseError, PortInUseError, SidecarExitedError, VersionMismatchError, } from "./errors.js";
27
+ import { createLogger } from "./logger.js";
28
+ import { currentPlatformKey, isPlaceholderSha, loadLock, resolveEntry, } from "./platform.js";
29
+ const log = createLogger("lifecycle");
30
+ export const DEFAULT_HOST = "127.0.0.1";
31
+ /** Matches `gaia_agent.server.DEFAULT_PORT`. NEVER 4001 (repo-reserved). */
32
+ export const DEFAULT_PORT = 8141;
33
+ /** Repo-wide reserved port. Nothing here may ever bind it. */
34
+ export const RESERVED_PORT = 4001;
35
+ /** The apiVersion this package is built against (`server.py: API_VERSION`). */
36
+ export const API_VERSION = "2.12";
37
+ /** The agent id in the sidecar's route prefix (`/v1/gaia/...`). */
38
+ export const AGENT_ID = "gaia";
39
+ /** Basename the sidecar executable is written as (matches the lock). */
40
+ export function sidecarExecutableName(platform = process.platform) {
41
+ return platform === "win32" ? "gaia-agent.exe" : "gaia-agent";
42
+ }
43
+ /**
44
+ * Basename the TUI executable is written as. Deliberately `gaia-tui`, not
45
+ * `gaia`: npm installs its own `gaia` bin shim, and a same-named executable in a
46
+ * cache dir on PATH would shadow it.
47
+ */
48
+ export function tuiExecutableName(platform = process.platform) {
49
+ return platform === "win32" ? "gaia-tui.exe" : "gaia-tui";
50
+ }
51
+ /** SHA-256 of a file, read in chunks so a ~200MB binary is not buffered whole. */
52
+ function fileSha256Sync(filePath) {
53
+ const hash = crypto.createHash("sha256");
54
+ const buf = Buffer.allocUnsafe(1 << 20);
55
+ const fd = fs.openSync(filePath, "r");
56
+ try {
57
+ for (;;) {
58
+ const n = fs.readSync(fd, buf, 0, buf.length, null);
59
+ if (n === 0)
60
+ break;
61
+ hash.update(buf.subarray(0, n));
62
+ }
63
+ }
64
+ finally {
65
+ fs.closeSync(fd);
66
+ }
67
+ return hash.digest("hex");
68
+ }
69
+ /**
70
+ * Re-verify an on-disk binary against the lock. `fetch.ts` calls the SHA verify
71
+ * "the security boundary"; this keeps that true for the resolve→spawn path,
72
+ * which is exported and whose cache path is guessable.
73
+ */
74
+ function verifyAgainstLock(full, component, lock) {
75
+ const platformKey = currentPlatformKey();
76
+ const entry = resolveEntry(lock ?? loadLock(), component, platformKey);
77
+ if (isPlaceholderSha(entry.sha256)) {
78
+ throw new IntegrityError(`binaries.lock.json has a placeholder sha256 for ${component}/'${platformKey}', ` +
79
+ `so ${full} cannot be verified and must not be spawned. Install a released ` +
80
+ "@amd-gaia/gaia, or pass { verify: false } if you built this binary yourself.");
81
+ }
82
+ const actual = fileSha256Sync(full);
83
+ if (actual.toLowerCase() !== entry.sha256.toLowerCase()) {
84
+ throw new IntegrityError(`SHA-256 mismatch for the ${component} binary at ${full}:\n` +
85
+ ` expected ${entry.sha256}\n` +
86
+ ` actual ${actual}\n` +
87
+ "Refusing to spawn a binary that does not match binaries.lock.json. " +
88
+ "Re-run `npx @amd-gaia/gaia fetch --force` to reinstall it; if it persists, " +
89
+ "report it at https://github.com/amd/gaia/issues.");
90
+ }
91
+ }
92
+ /** Resolve a fetched binary's path, failing loudly if it is not there. */
93
+ function resolveIn(opts, component, fallback, what) {
94
+ if (!opts?.resourcesDir) {
95
+ throw new TypeError("resolve requires { resourcesDir }");
96
+ }
97
+ const full = path.resolve(opts.resourcesDir, opts.executable ?? fallback);
98
+ if (!fs.existsSync(full)) {
99
+ throw new BinaryNotFoundError(`${what} binary not found at ${full} (platform ${currentPlatformKey()}). ` +
100
+ "Run the fetch step first: `npx @amd-gaia/gaia fetch`.");
101
+ }
102
+ if (opts.verify ?? true)
103
+ verifyAgainstLock(full, component, opts.lock);
104
+ return full;
105
+ }
106
+ export function resolveSidecarPath(opts) {
107
+ return resolveIn(opts, "sidecar", sidecarExecutableName(), "gaia-agent sidecar");
108
+ }
109
+ export function resolveTuiPath(opts) {
110
+ return resolveIn(opts, "tui", tuiExecutableName(), "gaia-tui");
111
+ }
112
+ // --- Auto-cleanup: reap orphaned sidecars when the parent process goes away ---
113
+ // The sidecar is spawned detached (its own process group), so a parent Ctrl+C,
114
+ // crash, or plain exit does NOT propagate to it — without this it keeps running
115
+ // and holds its port. Handlers are installed once and SIGKILL the tree
116
+ // synchronously on the way out. A hard SIGKILL of the parent is the one case no
117
+ // in-process handler can catch.
118
+ const liveSidecars = new Set();
119
+ let cleanupInstalled = false;
120
+ const CLEANUP_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
121
+ /** stderr from an exit handler: console.error can be async on a piped stderr. */
122
+ function writeStderrSync(msg) {
123
+ try {
124
+ fs.writeSync(2, msg.endsWith("\n") ? msg : `${msg}\n`);
125
+ }
126
+ catch {
127
+ /* stderr unavailable */
128
+ }
129
+ }
130
+ function killTreeSync(sidecar) {
131
+ const { child } = sidecar;
132
+ if (child.pid === undefined)
133
+ return;
134
+ if (child.exitCode !== null || child.signalCode !== null)
135
+ return;
136
+ try {
137
+ if (process.platform === "win32") {
138
+ const r = spawnSync("taskkill", ["/PID", String(child.pid), "/T", "/F"], {
139
+ stdio: ["ignore", "ignore", "pipe"],
140
+ encoding: "utf8",
141
+ });
142
+ // A refusal ("Access is denied") leaves the port held; say so now rather
143
+ // than let it surface as an unexplained bind failure on the next run.
144
+ if (r.error || r.status !== 0) {
145
+ writeStderrSync(`[gaia:lifecycle] ERROR taskkill /PID ${child.pid} /T /F failed ` +
146
+ `(${r.error ? r.error.message : `exit ${String(r.status)}`}): ` +
147
+ `${(r.stderr ?? "").trim() || "(no output)"}. ` +
148
+ `Kill pid ${child.pid} manually or port ${sidecar.port} stays bound.`);
149
+ }
150
+ }
151
+ else {
152
+ process.kill(-child.pid, "SIGKILL");
153
+ }
154
+ }
155
+ catch (e) {
156
+ const code = e.code;
157
+ if (code === "ESRCH")
158
+ return; // already gone — the outcome we wanted
159
+ writeStderrSync(`[gaia:lifecycle] ERROR could not kill the sidecar process group ` +
160
+ `${String(child.pid)}: ${e.message}. ` +
161
+ `Kill it manually or port ${sidecar.port} stays bound.`);
162
+ }
163
+ }
164
+ function reapAllSync() {
165
+ for (const s of liveSidecars)
166
+ killTreeSync(s);
167
+ liveSidecars.clear();
168
+ }
169
+ function crashHandler(err) {
170
+ reapAllSync();
171
+ try {
172
+ // Synchronous write — console.error can truncate on a piped stderr before
173
+ // process.exit flushes.
174
+ fs.writeSync(2, `${err instanceof Error ? (err.stack ?? err.message) : String(err)}\n`);
175
+ }
176
+ catch {
177
+ /* stderr unavailable */
178
+ }
179
+ process.exit(1);
180
+ }
181
+ /**
182
+ * True when ours is the only listener for `event`, i.e. nothing else in this
183
+ * process handles it and the process is therefore going down.
184
+ *
185
+ * Reaping is only ours to do in that case: a host with its own handler keeps
186
+ * running, and killing its sidecar would turn an exception it handled into an
187
+ * unexplained ECONNREFUSED on its next request.
188
+ */
189
+ function weOwnTheExit(event) {
190
+ return process.listenerCount(event) === 1;
191
+ }
192
+ function installCleanupHandlers() {
193
+ if (cleanupInstalled)
194
+ return;
195
+ cleanupInstalled = true;
196
+ // The backstop: whatever route the process takes out, this runs.
197
+ process.on("exit", reapAllSync);
198
+ // crashHandler reaps before it exits, so the guard is the whole handler.
199
+ process.on("uncaughtException", (err) => {
200
+ if (weOwnTheExit("uncaughtException"))
201
+ crashHandler(err);
202
+ });
203
+ process.on("unhandledRejection", (err) => {
204
+ if (weOwnTheExit("unhandledRejection"))
205
+ crashHandler(err);
206
+ });
207
+ for (const sig of CLEANUP_SIGNALS) {
208
+ const handler = () => {
209
+ if (!weOwnTheExit(sig))
210
+ return;
211
+ reapAllSync();
212
+ // Restore the default disposition and re-raise so we still terminate.
213
+ process.removeListener(sig, handler);
214
+ process.kill(process.pid, sig);
215
+ };
216
+ process.on(sig, handler);
217
+ }
218
+ }
219
+ function registerForCleanup(sidecar) {
220
+ installCleanupHandlers();
221
+ liveSidecars.add(sidecar);
222
+ sidecar.child.once("exit", () => liveSidecars.delete(sidecar));
223
+ }
224
+ /**
225
+ * Spawn the frozen sidecar. Does NOT wait for readiness — call `waitForHealth`
226
+ * (or `startSidecar`, which does both).
227
+ */
228
+ export function spawnSidecar(opts) {
229
+ if (!opts?.binaryPath) {
230
+ throw new TypeError("spawnSidecar requires { binaryPath }");
231
+ }
232
+ if (!fs.existsSync(opts.binaryPath)) {
233
+ throw new BinaryNotFoundError(`binary does not exist: ${opts.binaryPath}`);
234
+ }
235
+ const host = opts.host ?? DEFAULT_HOST;
236
+ const port = opts.port ?? DEFAULT_PORT;
237
+ if (port === RESERVED_PORT) {
238
+ throw new RangeError(`port ${RESERVED_PORT} is reserved and must never be used`);
239
+ }
240
+ const args = ["--host", host, "--port", String(port)];
241
+ if (opts.extraArgs?.length)
242
+ args.push(...opts.extraArgs);
243
+ log.info(`spawning ${opts.binaryPath} ${args.join(" ")}`);
244
+ const child = spawn(opts.binaryPath, args, {
245
+ // detached on POSIX → the child leads its own process group so we can signal
246
+ // the whole tree. Windows has different detach semantics; we use taskkill /T.
247
+ detached: process.platform !== "win32",
248
+ stdio: ["ignore", "pipe", "pipe"],
249
+ env: { ...process.env, ...(opts.env ?? {}) },
250
+ });
251
+ child.stdout?.on("data", (d) => log.debug(`[sidecar stdout] ${String(d).trimEnd()}`));
252
+ child.stderr?.on("data", (d) => log.debug(`[sidecar stderr] ${String(d).trimEnd()}`));
253
+ child.on("exit", (code, signal) => log.debug(`sidecar exited code=${code} signal=${signal}`));
254
+ child.on("error", (e) => log.error(`sidecar process error: ${e.message}`));
255
+ const sidecar = { child, host, port, baseUrl: `http://${host}:${port}` };
256
+ if (opts.autoCleanup !== false)
257
+ registerForCleanup(sidecar);
258
+ return sidecar;
259
+ }
260
+ async function getJson(url, timeoutMs, signal) {
261
+ const controller = new AbortController();
262
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
263
+ // Link the caller's signal so an in-flight probe aborts the moment the
264
+ // process being probed dies, rather than at the next poll.
265
+ const onAbort = () => controller.abort();
266
+ if (signal?.aborted)
267
+ controller.abort();
268
+ else
269
+ signal?.addEventListener("abort", onAbort, { once: true });
270
+ try {
271
+ const res = await fetch(url, {
272
+ headers: { accept: "application/json" },
273
+ signal: controller.signal,
274
+ });
275
+ const text = await res.text();
276
+ if (!res.ok)
277
+ throw new HttpError(res.status, url, text);
278
+ try {
279
+ return JSON.parse(text);
280
+ }
281
+ catch (e) {
282
+ // A proxy or captive portal answering 200 with HTML lands here; a bare
283
+ // SyntaxError would escape the CLI's GaiaError branch as a raw stack.
284
+ throw new MalformedResponseError(`${url} returned HTTP ${res.status} but its body is not JSON ` +
285
+ `(${e.message}). First 200 bytes: ${JSON.stringify(text.slice(0, 200))}. ` +
286
+ "Something other than the gaia sidecar is answering that address — " +
287
+ "check for a proxy on the port, or point at the right host/port.");
288
+ }
289
+ }
290
+ finally {
291
+ clearTimeout(timer);
292
+ signal?.removeEventListener("abort", onAbort);
293
+ }
294
+ }
295
+ /** `GET /health` — liveness only; it does not mean a model is loaded. */
296
+ export function health(baseUrl, timeoutMs = 1000, signal) {
297
+ return getJson(`${baseUrl}/health`, timeoutMs, signal);
298
+ }
299
+ /** `GET /version` — the contract probe (`{ apiVersion, agentVersion }`). */
300
+ export function version(baseUrl, timeoutMs = 5000) {
301
+ return getJson(`${baseUrl}/version`, timeoutMs);
302
+ }
303
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
304
+ /**
305
+ * Poll `GET /health` until the sidecar reports ok, or throw `HealthTimeoutError`.
306
+ * Never silently assumes ready.
307
+ */
308
+ export async function waitForHealth(baseUrl, opts = {}) {
309
+ const timeoutMs = opts.timeoutMs ?? 60_000;
310
+ const intervalMs = opts.intervalMs ?? 250;
311
+ const deadline = Date.now() + timeoutMs;
312
+ let lastErr = "";
313
+ let attempts = 0;
314
+ // Re-checked after every await, not just at the top of the loop: a probe that
315
+ // races the process's death would otherwise report a foreign server's health.
316
+ const throwIfAborted = () => {
317
+ if (!opts.signal?.aborted)
318
+ return;
319
+ throw new HealthTimeoutError(`health wait for ${baseUrl} was aborted after ${attempts} probe(s) ` +
320
+ "(the process being probed exited).");
321
+ };
322
+ while (Date.now() < deadline) {
323
+ throwIfAborted();
324
+ attempts++;
325
+ try {
326
+ const h = await health(baseUrl, intervalMs * 4, opts.signal);
327
+ throwIfAborted();
328
+ if (h.status === "ok") {
329
+ log.debug(`sidecar healthy after ${attempts} probe(s)`);
330
+ return;
331
+ }
332
+ lastErr = `unexpected health status: ${JSON.stringify(h)}`;
333
+ }
334
+ catch (e) {
335
+ throwIfAborted();
336
+ lastErr = e.message;
337
+ }
338
+ await sleep(intervalMs);
339
+ throwIfAborted();
340
+ }
341
+ throw new HealthTimeoutError(`the gaia sidecar at ${baseUrl} did not become healthy within ${timeoutMs}ms ` +
342
+ `(${attempts} probes). Last error: ${lastErr}. ` +
343
+ "Re-run with DEBUG=gaia to see the sidecar's own output, and check the port is free.");
344
+ }
345
+ /** Parse "2.12" → 2 (major). Throws on a non-numeric major. */
346
+ function majorOf(v) {
347
+ const major = Number.parseInt(String(v).split(".")[0] ?? "", 10);
348
+ if (Number.isNaN(major)) {
349
+ throw new VersionMismatchError(`cannot parse apiVersion major from '${v}'`);
350
+ }
351
+ return major;
352
+ }
353
+ /**
354
+ * Fetch `/version` and refuse a sidecar whose apiVersion MAJOR differs from what
355
+ * this package expects. A major bump is a breaking contract change; a higher
356
+ * minor (same major) is a backward-compatible addition and is accepted.
357
+ */
358
+ export async function checkVersion(baseUrl, opts = {}) {
359
+ const expected = opts.expectedApiVersion ?? API_VERSION;
360
+ const info = await version(baseUrl);
361
+ const expectedMajor = majorOf(expected);
362
+ const actualMajor = majorOf(info.apiVersion);
363
+ if (actualMajor !== expectedMajor) {
364
+ throw new VersionMismatchError(`incompatible gaia sidecar apiVersion: it reports '${info.apiVersion}' ` +
365
+ `(major ${actualMajor}) but this package expects major ${expectedMajor} ` +
366
+ `('${expected}'). A major bump is a breaking contract change. ` +
367
+ "Upgrade @amd-gaia/gaia to a version matching the sidecar.");
368
+ }
369
+ log.debug(`version OK: apiVersion=${info.apiVersion} agentVersion=${info.agentVersion}`);
370
+ return info;
371
+ }
372
+ /**
373
+ * Shut the sidecar down, killing the whole process tree. Resolves once the
374
+ * process has exited (or immediately if it already had).
375
+ */
376
+ export async function shutdown(sidecar, timeoutMs = 5000) {
377
+ const { child } = sidecar;
378
+ if (child.exitCode !== null || child.signalCode !== null || child.pid === undefined) {
379
+ liveSidecars.delete(sidecar);
380
+ log.debug("shutdown: sidecar already exited");
381
+ return;
382
+ }
383
+ const pid = child.pid;
384
+ log.info(`shutting down sidecar pid=${pid} (tree-kill)`);
385
+ const exited = new Promise((resolve) => {
386
+ child.once("exit", () => resolve());
387
+ });
388
+ // Why the kill was refused, kept for the throw below — "Access is denied" is
389
+ // the difference between "retry" and "run this elevated".
390
+ let killDiagnostic = "";
391
+ if (process.platform === "win32") {
392
+ const killer = spawn("taskkill", ["/PID", String(pid), "/T", "/F"], {
393
+ stdio: ["ignore", "ignore", "pipe"],
394
+ });
395
+ let taskkillErr = "";
396
+ killer.stderr?.on("data", (d) => {
397
+ taskkillErr += String(d);
398
+ });
399
+ killer.on("error", (e) => {
400
+ killDiagnostic = `taskkill could not be launched: ${e.message}`;
401
+ log.error(killDiagnostic);
402
+ });
403
+ killer.on("exit", (code) => {
404
+ if (code === 0)
405
+ return;
406
+ killDiagnostic =
407
+ `taskkill /PID ${pid} /T /F exited ${String(code)}: ` +
408
+ `${taskkillErr.trim() || "(no output)"}`;
409
+ log.error(killDiagnostic);
410
+ });
411
+ }
412
+ else {
413
+ try {
414
+ process.kill(-pid, "SIGTERM"); // negative pid → the whole process group
415
+ }
416
+ catch (e) {
417
+ log.debug(`SIGTERM to group failed (${e.message}); trying direct`);
418
+ try {
419
+ child.kill("SIGTERM");
420
+ }
421
+ catch {
422
+ /* already gone */
423
+ }
424
+ }
425
+ }
426
+ const raceExit = async (ms) => {
427
+ let t;
428
+ const timer = new Promise((resolve) => {
429
+ t = setTimeout(() => resolve("timeout"), ms);
430
+ });
431
+ return Promise.race([exited.then(() => "exited"), timer]).finally(() => clearTimeout(t));
432
+ };
433
+ if ((await raceExit(timeoutMs)) === "timeout") {
434
+ log.warn(`sidecar did not exit within ${timeoutMs}ms; forcing`);
435
+ if (process.platform !== "win32") {
436
+ try {
437
+ process.kill(-pid, "SIGKILL");
438
+ }
439
+ catch {
440
+ /* gone */
441
+ }
442
+ }
443
+ // Bound the final wait too. On Windows there is no second escalation after
444
+ // taskkill, so an unbounded await here would hang Ctrl+C forever.
445
+ if ((await raceExit(timeoutMs)) === "timeout") {
446
+ // Deliberately still registered: the process-exit reaper is the last
447
+ // chance to reap a survivor, and de-registering here would orphan it.
448
+ throw new Error(`the gaia sidecar (pid ${pid}) did not exit after a forced kill` +
449
+ (killDiagnostic ? ` (${killDiagnostic})` : "") +
450
+ ". Kill it manually — " +
451
+ (process.platform === "win32"
452
+ ? `taskkill /PID ${pid} /T /F`
453
+ : `kill -9 -${pid}`) +
454
+ ` — or port ${sidecar.port} stays bound.`);
455
+ }
456
+ }
457
+ liveSidecars.delete(sidecar);
458
+ log.info("sidecar shut down");
459
+ }
460
+ /**
461
+ * Refuse a handle whose own child is dead. A healthy `/health` proves *something*
462
+ * owns the port — this proves it is ours. Without it a second `gaia serve` would
463
+ * print a ready URL for a server it cannot shut down.
464
+ */
465
+ function assertOurs(sidecar) {
466
+ const { child } = sidecar;
467
+ if (child.exitCode === null && child.signalCode === null)
468
+ return;
469
+ throw new SidecarExitedError(`the gaia sidecar we spawned exited (code=${String(child.exitCode)} ` +
470
+ `signal=${String(child.signalCode)}) while ${sidecar.baseUrl}/health still ` +
471
+ `answered — another process is already bound to port ${sidecar.port}, most ` +
472
+ "likely an instance you started earlier. Stop it (" +
473
+ (process.platform === "win32"
474
+ ? `netstat -ano | findstr :${sidecar.port}`
475
+ : `lsof -i :${sidecar.port}`) +
476
+ ") or start on a different port with --port. Re-run with DEBUG=gaia to see " +
477
+ "the sidecar's own output.");
478
+ }
479
+ /**
480
+ * Decide what a dead child actually means, by asking who owns the port now.
481
+ *
482
+ * The health wait aborts the instant our child exits, so on a fast machine that
483
+ * abort can beat a healthy reply from an incumbent — and then a port conflict
484
+ * reports as a plain timeout. Re-probing settles which failure this is instead
485
+ * of letting the race name it. Silent when our child is alive, or when nothing
486
+ * answers: that is a genuine timeout and the caller rethrows it.
487
+ */
488
+ async function assertNotAForeignServer(sidecar) {
489
+ const { child } = sidecar;
490
+ if (child.exitCode === null && child.signalCode === null)
491
+ return;
492
+ try {
493
+ if ((await health(sidecar.baseUrl, 1_000)).status !== "ok")
494
+ return;
495
+ }
496
+ catch {
497
+ return; // nothing is listening — our sidecar simply died
498
+ }
499
+ assertOurs(sidecar); // something else owns the port; throws SidecarExitedError
500
+ }
501
+ /**
502
+ * True when something is already listening on host:port.
503
+ *
504
+ * A TCP connect, not a `/health` probe: ANY listener makes our bind fail, and
505
+ * the incumbent need not be a GAIA sidecar. Unreachable-in-time counts as free —
506
+ * this exists to turn a confusing failure into a clear one early, and the
507
+ * spawn + health wait remains the actual gate.
508
+ */
509
+ function portInUse(host, port, timeoutMs = 500) {
510
+ return new Promise((resolve) => {
511
+ const socket = net.connect({ host, port });
512
+ const settle = (inUse) => {
513
+ socket.destroy();
514
+ resolve(inUse);
515
+ };
516
+ socket.setTimeout(timeoutMs, () => settle(false));
517
+ socket.once("connect", () => settle(true));
518
+ socket.once("error", () => settle(false)); // ECONNREFUSED — nothing there
519
+ });
520
+ }
521
+ /**
522
+ * Spawn → wait for health → assert the child is still ours → (optionally)
523
+ * version-check. On any failure the sidecar is shut down before rethrowing, so a
524
+ * failed start never leaks a process.
525
+ *
526
+ * The port is checked BEFORE the spawn. Without that, the frozen sidecar spends
527
+ * seconds unpacking before it even attempts its bind, while an incumbent answers
528
+ * `/health` in milliseconds — so the health wait succeeds, the still-unpacking
529
+ * child looks alive, and we would hand back a handle for a server we do not own.
530
+ * `assertOurs` / `assertNotAForeignServer` stay as backstops for the narrower
531
+ * race where something binds after this check.
532
+ */
533
+ export async function startSidecar(opts) {
534
+ const host = opts.host ?? DEFAULT_HOST;
535
+ const port = opts.port ?? DEFAULT_PORT;
536
+ if (await portInUse(host, port)) {
537
+ throw new PortInUseError(`port ${port} on ${host} is already in use, so the gaia sidecar cannot bind ` +
538
+ "it. Most likely an instance you started earlier is still running. Find it " +
539
+ "with " +
540
+ (process.platform === "win32"
541
+ ? `\`netstat -ano | findstr :${port}\``
542
+ : `\`lsof -i :${port}\``) +
543
+ `, then stop it — or start on a different port with --port. Nothing was ` +
544
+ "spawned.");
545
+ }
546
+ const sidecar = spawnSidecar(opts);
547
+ // A sidecar that dies immediately (missing runtime lib, port already bound)
548
+ // must not make the caller wait out the full health timeout.
549
+ const died = new AbortController();
550
+ sidecar.child.once("exit", () => died.abort());
551
+ try {
552
+ try {
553
+ await waitForHealth(sidecar.baseUrl, {
554
+ timeoutMs: opts.healthTimeoutMs,
555
+ signal: died.signal,
556
+ });
557
+ }
558
+ catch (e) {
559
+ await assertNotAForeignServer(sidecar);
560
+ throw e;
561
+ }
562
+ assertOurs(sidecar);
563
+ if (opts.verifyVersion ?? true) {
564
+ await checkVersion(sidecar.baseUrl, {
565
+ expectedApiVersion: opts.expectedApiVersion,
566
+ });
567
+ assertOurs(sidecar);
568
+ }
569
+ return sidecar;
570
+ }
571
+ catch (e) {
572
+ log.error(`startSidecar failed (${e.message}); shutting down`);
573
+ await shutdown(sidecar).catch(() => undefined);
574
+ throw e;
575
+ }
576
+ }
577
+ /**
578
+ * Run the TUI in the foreground with stdio inherited and resolve with its exit
579
+ * code. A signal-terminated TUI resolves as 128 + signum, the shell convention,
580
+ * so a Ctrl+C is distinguishable from a clean exit 0.
581
+ */
582
+ export function runTui(opts) {
583
+ if (!opts?.binaryPath) {
584
+ throw new TypeError("runTui requires { binaryPath }");
585
+ }
586
+ if (!fs.existsSync(opts.binaryPath)) {
587
+ throw new BinaryNotFoundError(`gaia-tui binary does not exist: ${opts.binaryPath}`);
588
+ }
589
+ return new Promise((resolve, reject) => {
590
+ const child = spawn(opts.binaryPath, opts.args ?? [], {
591
+ stdio: "inherit",
592
+ env: { ...process.env, ...(opts.env ?? {}) },
593
+ });
594
+ child.on("error", (e) => reject(new BinaryNotFoundError(`could not launch the TUI at ${opts.binaryPath}: ${e.message}`)));
595
+ child.on("exit", (code, signal) => {
596
+ if (signal) {
597
+ resolve(128 + (SIGNUM[signal] ?? 0));
598
+ return;
599
+ }
600
+ resolve(code ?? 0);
601
+ });
602
+ });
603
+ }
604
+ // Only the signals a foreground TUI realistically dies from; anything else maps
605
+ // to 128, which still reads as "terminated by a signal".
606
+ const SIGNUM = {
607
+ SIGHUP: 1,
608
+ SIGINT: 2,
609
+ SIGQUIT: 3,
610
+ SIGKILL: 9,
611
+ SIGTERM: 15,
612
+ };
613
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,+BAA+B;AAC/B;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAqB,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAGL,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,YAAY,GACb,MAAM,eAAe,CAAC;AAEvB,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;AAEtC,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC;AAExC,4EAA4E;AAC5E,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AAEjC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAElC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAElC,mEAAmE;AACnE,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC;AAc/B,wEAAwE;AACxE,MAAM,UAAU,qBAAqB,CACnC,WAA4B,OAAO,CAAC,QAAQ;IAE5C,OAAO,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC;AAChE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,WAA4B,OAAO,CAAC,QAAQ;IAE5C,OAAO,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;AAC5D,CAAC;AAkBD,kFAAkF;AAClF,SAAS,cAAc,CAAC,QAAgB;IACtC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,SAAS,CAAC;YACR,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACpD,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM;YACnB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CACxB,IAAY,EACZ,SAAwB,EACxB,IAA4B;IAE5B,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,IAAI,QAAQ,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACvE,IAAI,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,cAAc,CACtB,mDAAmD,SAAS,KAAK,WAAW,KAAK;YAC/E,MAAM,IAAI,kEAAkE;YAC5E,8EAA8E,CACjF,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;QACxD,MAAM,IAAI,cAAc,CACtB,4BAA4B,SAAS,cAAc,IAAI,KAAK;YAC1D,cAAc,KAAK,CAAC,MAAM,IAAI;YAC9B,cAAc,MAAM,IAAI;YACxB,qEAAqE;YACrE,6EAA6E;YAC7E,kDAAkD,CACrD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,SAAS,SAAS,CAChB,IAAoB,EACpB,SAAwB,EACxB,QAAgB,EAChB,IAAY;IAEZ,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;QACxB,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,IAAI,QAAQ,CAAC,CAAC;IAC1E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,mBAAmB,CAC3B,GAAG,IAAI,wBAAwB,IAAI,cAAc,kBAAkB,EAAE,KAAK;YACxE,uDAAuD,CAC1D,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI;QAAE,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACvE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAoB;IACrD,OAAO,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,EAAE,oBAAoB,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAoB;IACjD,OAAO,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,UAAU,CAAC,CAAC;AACjE,CAAC;AA6BD,iFAAiF;AACjF,+EAA+E;AAC/E,gFAAgF;AAChF,uEAAuE;AACvE,gFAAgF;AAChF,gCAAgC;AAChC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAW,CAAC;AACxC,IAAI,gBAAgB,GAAG,KAAK,CAAC;AAC7B,MAAM,eAAe,GAAqB,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAE1E,iFAAiF;AACjF,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,wBAAwB;IAC1B,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,OAAgB;IACpC,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAC1B,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS;QAAE,OAAO;IACpC,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;QAAE,OAAO;IACjE,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,MAAM,CAAC,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE;gBACvE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC;gBACnC,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAC;YACH,yEAAyE;YACzE,sEAAsE;YACtE,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,eAAe,CACb,wCAAwC,KAAK,CAAC,GAAG,gBAAgB;oBAC/D,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK;oBAC/D,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,aAAa,IAAI;oBAC/C,YAAY,KAAK,CAAC,GAAG,qBAAqB,OAAO,CAAC,IAAI,eAAe,CACxE,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,GAAI,CAA2B,CAAC,IAAI,CAAC;QAC/C,IAAI,IAAI,KAAK,OAAO;YAAE,OAAO,CAAC,uCAAuC;QACrE,eAAe,CACb,kEAAkE;YAChE,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAM,CAAW,CAAC,OAAO,IAAI;YACjD,4BAA4B,OAAO,CAAC,IAAI,eAAe,CAC1D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,WAAW;IAClB,KAAK,MAAM,CAAC,IAAI,YAAY;QAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9C,YAAY,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC;AAED,SAAS,YAAY,CAAC,GAAY;IAChC,WAAW,EAAE,CAAC;IACd,IAAI,CAAC;QACH,0EAA0E;QAC1E,wBAAwB;QACxB,EAAE,CAAC,SAAS,CACV,CAAC,EACD,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CACvE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,wBAAwB;IAC1B,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,sBAAsB;IAC7B,IAAI,gBAAgB;QAAE,OAAO;IAC7B,gBAAgB,GAAG,IAAI,CAAC;IACxB,iEAAiE;IACjE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAChC,yEAAyE;IACzE,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE;QACtC,IAAI,YAAY,CAAC,mBAAmB,CAAC;YAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,GAAG,EAAE,EAAE;QACvC,IAAI,YAAY,CAAC,oBAAoB,CAAC;YAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IACH,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC;gBAAE,OAAO;YAC/B,WAAW,EAAE,CAAC;YACd,sEAAsE;YACtE,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACjC,CAAC,CAAC;QACF,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAgB;IAC1C,sBAAsB,EAAE,CAAC;IACzB,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAkB;IAC7C,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC;QACtB,MAAM,IAAI,SAAS,CAAC,sCAAsC,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,mBAAmB,CAAC,0BAA0B,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC;IACvC,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAAC,QAAQ,aAAa,qCAAqC,CAAC,CAAC;IACnF,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IACtD,IAAI,IAAI,CAAC,SAAS,EAAE,MAAM;QAAE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAEzD,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAE1D,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE;QACzC,6EAA6E;QAC7E,8EAA8E;QAC9E,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;QACtC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;QACjC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE;KAC7C,CAAC,CAAC;IAEH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,oBAAoB,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IACtF,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,oBAAoB,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IACtF,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAChC,GAAG,CAAC,KAAK,CAAC,uBAAuB,IAAI,WAAW,MAAM,EAAE,CAAC,CAC1D,CAAC;IACF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAE3E,MAAM,OAAO,GAAY,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;IAClF,IAAI,IAAI,CAAC,WAAW,KAAK,KAAK;QAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,OAAO,CACpB,GAAW,EACX,SAAiB,EACjB,MAAoB;IAEpB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAC9D,uEAAuE;IACvE,2DAA2D;IAC3D,MAAM,OAAO,GAAG,GAAS,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC/C,IAAI,MAAM,EAAE,OAAO;QAAE,UAAU,CAAC,KAAK,EAAE,CAAC;;QACnC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;YACvC,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACxD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;QAC/B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,uEAAuE;YACvE,sEAAsE;YACtE,MAAM,IAAI,sBAAsB,CAC9B,GAAG,GAAG,kBAAkB,GAAG,CAAC,MAAM,4BAA4B;gBAC5D,IAAK,CAAW,CAAC,OAAO,uBAAuB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI;gBACrF,oEAAoE;gBACpE,iEAAiE,CACpE,CAAC;QACJ,CAAC;IACH,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,MAAM,CACpB,OAAe,EACf,SAAS,GAAG,IAAI,EAChB,MAAoB;IAEpB,OAAO,OAAO,CAAiB,GAAG,OAAO,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;AACzE,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,SAAS,GAAG,IAAI;IACvD,OAAO,OAAO,CAAkB,GAAG,OAAO,UAAU,EAAE,SAAS,CAAC,CAAC;AACnE,CAAC;AAWD,MAAM,KAAK,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAEnF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,OAA6B,EAAE;IAE/B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAM,cAAc,GAAG,GAAS,EAAE;QAChC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO;YAAE,OAAO;QAClC,MAAM,IAAI,kBAAkB,CAC1B,mBAAmB,OAAO,sBAAsB,QAAQ,YAAY;YAClE,oCAAoC,CACvC,CAAC;IACJ,CAAC,CAAC;IACF,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,cAAc,EAAE,CAAC;QACjB,QAAQ,EAAE,CAAC;QACX,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7D,cAAc,EAAE,CAAC;YACjB,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBACtB,GAAG,CAAC,KAAK,CAAC,yBAAyB,QAAQ,WAAW,CAAC,CAAC;gBACxD,OAAO;YACT,CAAC;YACD,OAAO,GAAG,6BAA6B,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,cAAc,EAAE,CAAC;YACjB,OAAO,GAAI,CAAW,CAAC,OAAO,CAAC;QACjC,CAAC;QACD,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;QACxB,cAAc,EAAE,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,kBAAkB,CAC1B,uBAAuB,OAAO,kCAAkC,SAAS,KAAK;QAC5E,IAAI,QAAQ,yBAAyB,OAAO,IAAI;QAChD,qFAAqF,CACxF,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,SAAS,OAAO,CAAC,CAAS;IACxB,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACjE,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,oBAAoB,CAAC,uCAAuC,CAAC,GAAG,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAOD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAe,EACf,OAA4B,EAAE;IAE9B,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,IAAI,WAAW,CAAC;IACxD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7C,IAAI,WAAW,KAAK,aAAa,EAAE,CAAC;QAClC,MAAM,IAAI,oBAAoB,CAC5B,qDAAqD,IAAI,CAAC,UAAU,IAAI;YACtE,UAAU,WAAW,oCAAoC,aAAa,GAAG;YACzE,KAAK,QAAQ,kDAAkD;YAC/D,2DAA2D,CAC9D,CAAC;IACJ,CAAC;IACD,GAAG,CAAC,KAAK,CAAC,0BAA0B,IAAI,CAAC,UAAU,iBAAiB,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IACzF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAgB,EAAE,SAAS,GAAG,IAAI;IAC/D,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAC1B,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QACpF,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7B,GAAG,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;IACtB,GAAG,CAAC,IAAI,CAAC,6BAA6B,GAAG,cAAc,CAAC,CAAC;IAEzD,MAAM,MAAM,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAC3C,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAC7E,0DAA0D;IAC1D,IAAI,cAAc,GAAG,EAAE,CAAC;IAExB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE;YAClE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC;SACpC,CAAC,CAAC;QACH,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;YAC9B,WAAW,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;YACvB,cAAc,GAAG,mCAAmC,CAAC,CAAC,OAAO,EAAE,CAAC;YAChE,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO;YACvB,cAAc;gBACZ,iBAAiB,GAAG,iBAAiB,MAAM,CAAC,IAAI,CAAC,IAAI;oBACrD,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,aAAa,EAAE,CAAC;YAC3C,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,yCAAyC;QAC1E,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,GAAG,CAAC,KAAK,CAAC,4BAA6B,CAAW,CAAC,OAAO,kBAAkB,CAAC,CAAC;YAC9E,IAAI,CAAC;gBACH,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,kBAAkB;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,EAAE,EAAU,EAAiC,EAAE;QACnE,IAAI,CAAiB,CAAC;QACtB,MAAM,KAAK,GAAG,IAAI,OAAO,CAAY,CAAC,OAAO,EAAE,EAAE;YAC/C,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAiB,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAC9E,YAAY,CAAC,CAAC,CAAC,CAChB,CAAC;IACJ,CAAC,CAAC;IAEF,IAAI,CAAC,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC9C,GAAG,CAAC,IAAI,CAAC,+BAA+B,SAAS,aAAa,CAAC,CAAC;QAChE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,UAAU;YACZ,CAAC;QACH,CAAC;QACD,2EAA2E;QAC3E,kEAAkE;QAClE,IAAI,CAAC,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YAC9C,qEAAqE;YACrE,sEAAsE;YACtE,MAAM,IAAI,KAAK,CACb,yBAAyB,GAAG,oCAAoC;gBAC9D,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,cAAc,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9C,uBAAuB;gBACvB,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO;oBAC3B,CAAC,CAAC,iBAAiB,GAAG,QAAQ;oBAC9B,CAAC,CAAC,YAAY,GAAG,EAAE,CAAC;gBACtB,cAAc,OAAO,CAAC,IAAI,eAAe,CAC5C,CAAC;QACJ,CAAC;IACH,CAAC;IACD,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;AAChC,CAAC;AAWD;;;;GAIG;AACH,SAAS,UAAU,CAAC,OAAgB;IAClC,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAC1B,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;QAAE,OAAO;IACjE,MAAM,IAAI,kBAAkB,CAC1B,4CAA4C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG;QACnE,UAAU,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,OAAO,CAAC,OAAO,gBAAgB;QAC5E,uDAAuD,OAAO,CAAC,IAAI,SAAS;QAC5E,mDAAmD;QACnD,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO;YAC3B,CAAC,CAAC,2BAA2B,OAAO,CAAC,IAAI,EAAE;YAC3C,CAAC,CAAC,YAAY,OAAO,CAAC,IAAI,EAAE,CAAC;QAC/B,4EAA4E;QAC5E,2BAA2B,CAC9B,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,uBAAuB,CAAC,OAAgB;IACrD,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAC1B,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;QAAE,OAAO;IACjE,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI;YAAE,OAAO;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,iDAAiD;IAC3D,CAAC;IACD,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,0DAA0D;AACjF,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,SAAS,CAAC,IAAY,EAAE,IAAY,EAAE,SAAS,GAAG,GAAG;IAC5D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,CAAC,KAAc,EAAQ,EAAE;YACtC,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC;QACF,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,+BAA+B;IAC5E,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAkB;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC;IACvC,IAAI,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,cAAc,CACtB,QAAQ,IAAI,OAAO,IAAI,sDAAsD;YAC3E,4EAA4E;YAC5E,OAAO;YACP,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO;gBAC3B,CAAC,CAAC,6BAA6B,IAAI,IAAI;gBACvC,CAAC,CAAC,cAAc,IAAI,IAAI,CAAC;YAC3B,yEAAyE;YACzE,UAAU,CACb,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,4EAA4E;IAC5E,6DAA6D;IAC7D,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;IACnC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC/C,IAAI,CAAC;QACH,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE;gBACnC,SAAS,EAAE,IAAI,CAAC,eAAe;gBAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,uBAAuB,CAAC,OAAO,CAAC,CAAC;YACvC,MAAM,CAAC,CAAC;QACV,CAAC;QACD,UAAU,CAAC,OAAO,CAAC,CAAC;QACpB,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC;YAC/B,MAAM,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE;gBAClC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;aAC5C,CAAC,CAAC;YACH,UAAU,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,KAAK,CAAC,wBAAyB,CAAW,CAAC,OAAO,kBAAkB,CAAC,CAAC;QAC1E,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,IAAmB;IACxC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC;QACtB,MAAM,IAAI,SAAS,CAAC,gCAAgC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,mBAAmB,CAAC,mCAAmC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE;YACpD,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE;SAC7C,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CACtB,MAAM,CACJ,IAAI,mBAAmB,CACrB,+BAA+B,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC,OAAO,EAAE,CAC/D,CACF,CACF,CAAC;QACF,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YAChC,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACrC,OAAO;YACT,CAAC;YACD,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,gFAAgF;AAChF,yDAAyD;AACzD,MAAM,MAAM,GAA2B;IACrC,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,EAAE;CACZ,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Minimal namespaced logger. Debug output is OFF by default and enabled via the
3
+ * `DEBUG` env var (substring match on `gaia`, or `*`). Everything goes to stderr
4
+ * so it never corrupts stdout — which the TUI owns once it is exec'd.
5
+ */
6
+ export interface Logger {
7
+ debug(msg: string, ...rest: unknown[]): void;
8
+ info(msg: string, ...rest: unknown[]): void;
9
+ warn(msg: string, ...rest: unknown[]): void;
10
+ error(msg: string, ...rest: unknown[]): void;
11
+ }
12
+ export declare function createLogger(namespace: string): Logger;
13
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAOH,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC7C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC5C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAC9C;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAgBtD"}