seedcord 0.16.0-next.9 → 0.16.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/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as SEEDCORD_CONFIG_FILENAMES, t as version } from "./src-CYYGi1vs.mjs";
1
+ import { n as SEEDCORD_CONFIG_FILENAMES, t as version } from "./src-pMIoZiL7.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import { Command } from "@commander-js/extra-typings";
4
4
  import { LEVEL_COLOR, Logger, LoggerChannelRegistry } from "@seedcord/logger";
@@ -6,7 +6,7 @@ import { formatBody, installNodeDefaults } from "@seedcord/logger/node";
6
6
  import { SeedcordErrorCode, isSeedcordError } from "@seedcord/errors";
7
7
  import { existsSync } from "node:fs";
8
8
  import { SeedcordError, validateDiscordToken } from "@seedcord/errors/internal";
9
- import { dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
9
+ import { dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
10
10
  import { pathToFileURL } from "node:url";
11
11
  import { createJiti } from "jiti";
12
12
  import { tsImport } from "tsx/esm/api";
@@ -22,7 +22,7 @@ import chalk from "chalk";
22
22
  import { autocompleteMultiselect, cancel, confirm, intro, isCancel, log, multiselect, note, outro, select, spinner } from "@clack/prompts";
23
23
  import { createInterface } from "node:readline";
24
24
  import { Box, Text, measureElement, render, useAnimation, useInput, useWindowSize } from "ink";
25
- import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
25
+ import React, { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
26
26
  import { TypedEventEmitter } from "@seedcord/event-emitter";
27
27
  import Spinner from "ink-spinner";
28
28
  import { assertNever } from "@seedcord/utils";
@@ -36,10 +36,10 @@ var BaseCommand = class {
36
36
  name;
37
37
  description;
38
38
  logger;
39
- constructor(name, description, loggerChannel) {
39
+ constructor(name, description, label) {
40
40
  this.name = name;
41
41
  this.description = description;
42
- this.logger = new Logger(loggerChannel);
42
+ this.logger = new Logger(label, { channel: "cli" });
43
43
  }
44
44
  };
45
45
 
@@ -461,7 +461,7 @@ var BuildRunner = class BuildRunner {
461
461
  var BuildCommand = class extends BaseCommand {
462
462
  runner;
463
463
  constructor() {
464
- super("build", "Compile a Seedcord project from the config file", "CLI:Build");
464
+ super("build", "Compile a Seedcord project from the config file", "Build");
465
465
  this.runner = BuildRunner.create(this.logger);
466
466
  }
467
467
  register(program) {
@@ -589,11 +589,19 @@ var AugmentationBuilder = class {
589
589
  //#region src/commands/codegen/renderAugmentation.ts
590
590
  const BANNER = `// Generated by \`seedcord codegen\`. Do not edit by hand.
591
591
  // Run \`seedcord codegen\` after changing your commands or emoji config.`;
592
+ const BOT_BINDING = "Bot";
592
593
  const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
593
594
  const CONTROL_CHAR = 32;
594
595
  const HEX_RADIX = 16;
595
- function renderAugmentation(registry, target) {
596
- return `${BANNER}\n\n// prettier-ignore\ndeclare module '${target}' {\n interface SlashOptionRegistry {\n${renderSlashRows(registry.slash)}\n }\n interface UserContextMenuRegistry {\n${renderContextMenuRows(registry.userContextMenus)}\n }\n interface MessageContextMenuRegistry {\n${renderContextMenuRows(registry.messageContextMenus)}\n }\n interface EmojiMap {\n${renderEmojiRows(registry.emojis)}\n }\n}\n\nexport {};\n`;
596
+ function renderAugmentation(registry, target, plugins) {
597
+ const keys = [...plugins?.keys ?? []].sort(compare);
598
+ const attached = plugins !== void 0 && keys.length > 0;
599
+ const botImport = attached ? `import type ${BOT_BINDING} from '${escapeLiteral(plugins.specifier)}';\n\n` : "";
600
+ const coreRows = attached ? ` interface Core {\n${renderPluginRows(keys)}\n }\n` : "";
601
+ return `${`${BANNER}\n\n${botImport}// prettier-ignore\ndeclare module '${target}' {\n` + coreRows} interface SlashOptionRegistry {\n${renderSlashRows(registry.slash)}\n }\n interface UserContextMenuRegistry {\n${renderContextMenuRows(registry.userContextMenus)}\n }\n interface MessageContextMenuRegistry {\n${renderContextMenuRows(registry.messageContextMenus)}\n }\n interface EmojiMap {\n${renderEmojiRows(registry.emojis)}\n }\n}\n\nexport {};\n`;
602
+ }
603
+ function renderPluginRows(keys) {
604
+ return keys.map((key) => ` ${renderKey(key)}: (typeof ${BOT_BINDING})['${escapeLiteral(key)}'];`).join("\n");
597
605
  }
598
606
  function renderSlashRows(tables) {
599
607
  return Object.entries(tables).sort(([first], [second]) => compare(first, second)).map(([route, options]) => ` ${renderKey(route)}: ${renderRow(options)};`).join("\n");
@@ -660,6 +668,11 @@ function compare(first, second) {
660
668
  //#endregion
661
669
  //#region src/commands/codegen/CodegenRunner.ts
662
670
  const OUTPUT_FILENAME = "seedcord-gen.d.ts";
671
+ const ENTRY_EXTENSION = /\.[mc]?[jt]sx?$/;
672
+ function botSpecifier(root, instance) {
673
+ const posix = relative(root, instance).split(sep).join("/").replace(ENTRY_EXTENSION, "");
674
+ return posix.startsWith(".") ? posix : `./${posix}`;
675
+ }
663
676
  /**
664
677
  * Orchestrates `seedcord codegen`. Locates and loads the CLI config, imports the user's Seedcord instance to
665
678
  * read its commands directory and emoji config, scans and instantiates each command for its `toJSON()`, then
@@ -684,8 +697,11 @@ var CodegenRunner = class CodegenRunner {
684
697
  }
685
698
  async run(check) {
686
699
  const config = await this.loadConfig();
687
- const { commands, emojis, augmentTarget } = await this.scan(config);
688
- const rendered = renderAugmentation(this.generator.generate(commands, emojis), augmentTarget);
700
+ const { commands, emojis, augmentTarget, pluginKeys } = await this.scan(config);
701
+ const rendered = renderAugmentation(this.generator.generate(commands, emojis), augmentTarget, {
702
+ specifier: botSpecifier(config.root, config.instance),
703
+ keys: pluginKeys
704
+ });
689
705
  const outputPath = resolve(config.root, OUTPUT_FILENAME);
690
706
  if (check) {
691
707
  await this.check(rendered, outputPath);
@@ -697,13 +713,14 @@ var CodegenRunner = class CodegenRunner {
697
713
  return this.configLoader.load(this.locator.locate());
698
714
  }
699
715
  async scan(config) {
700
- const { commandsDir, emojis, augmentTarget } = await this.resolveInstance(config);
716
+ const { commandsDir, emojis, augmentTarget, pluginKeys } = await this.resolveInstance(config);
701
717
  const commands = [];
702
718
  if (commandsDir) for await (const command of this.walk(commandsDir, /* @__PURE__ */ new Set(), true)) commands.push(command);
703
719
  return {
704
720
  commands,
705
721
  emojis,
706
- augmentTarget
722
+ augmentTarget,
723
+ pluginKeys
707
724
  };
708
725
  }
709
726
  async *walk(dir, seen, isRoot) {
@@ -741,7 +758,8 @@ var CodegenRunner = class CodegenRunner {
741
758
  return {
742
759
  commandsDir: commandsPath ? resolve(process.cwd(), commandsPath) : void 0,
743
760
  emojis: instance.config.bot.emojis ?? {},
744
- augmentTarget: instance.augmentTarget
761
+ augmentTarget: instance.augmentTarget,
762
+ pluginKeys: instance.pluginKeys
745
763
  };
746
764
  }
747
765
  commandJsonOf(exported) {
@@ -788,7 +806,7 @@ var CodegenRunner = class CodegenRunner {
788
806
  var CodegenCommand = class extends BaseCommand {
789
807
  runner;
790
808
  constructor() {
791
- super("codegen", "Generate typed augmentations (slash options, context menus, emojis) from your commands and config", "CLI:Codegen");
809
+ super("codegen", "Generate typed augmentations from your commands and config", "Codegen");
792
810
  this.runner = CodegenRunner.create(this.logger);
793
811
  }
794
812
  register(program) {
@@ -1358,7 +1376,7 @@ function hasCleanFlags(options) {
1358
1376
  var CommandsCommand = class extends BaseCommand {
1359
1377
  cleanRunner;
1360
1378
  constructor() {
1361
- super("commands", "Inspect and clean deployed guild commands", "CLI:Commands");
1379
+ super("commands", "Inspect and clean deployed guild commands", "Commands");
1362
1380
  this.cleanRunner = CleanRunner.create();
1363
1381
  }
1364
1382
  register(program) {
@@ -1411,7 +1429,7 @@ const INITIAL_CURSOR = {
1411
1429
  levels: 0
1412
1430
  };
1413
1431
  function moveCursor(cursor, move, channelCount, levelCount) {
1414
- if (move === "up" || move === "down") return {
1432
+ if (move === "switch") return {
1415
1433
  ...cursor,
1416
1434
  group: cursor.group === "channels" ? "levels" : "channels"
1417
1435
  };
@@ -1554,6 +1572,25 @@ function useLogs(channels, levels) {
1554
1572
  ]);
1555
1573
  }
1556
1574
 
1575
+ //#endregion
1576
+ //#region src/ui/hooks/useMeasuredHeight.ts
1577
+ /**
1578
+ * The rendered height of a box, 0 until the first measurement lands.
1579
+ *
1580
+ * No dep array. A box moves for reasons its caller cannot enumerate, and one of them can be derived from the
1581
+ * height itself, which rules out a dependency list. The equality bail is what keeps the per-render measurement
1582
+ * from forming an update chain.
1583
+ */
1584
+ function useMeasuredHeight(ref) {
1585
+ const [height, setHeight] = useState(0);
1586
+ useLayoutEffect(() => {
1587
+ if (!ref.current) return;
1588
+ const next = measureElement(ref.current).height;
1589
+ setHeight((prev) => prev === next ? prev : next);
1590
+ });
1591
+ return height;
1592
+ }
1593
+
1557
1594
  //#endregion
1558
1595
  //#region src/ui/hooks/useRailWidth.ts
1559
1596
  function useRailWidth(railRef, phase, rows, columns) {
@@ -1640,7 +1677,6 @@ function useScroll(items, viewportHeight, getKey) {
1640
1677
  //#endregion
1641
1678
  //#region src/ui/palette.ts
1642
1679
  const ui = {
1643
- heading: "#7aa2f7",
1644
1680
  accent: "#7dcfff",
1645
1681
  muted: "#9aa0b3",
1646
1682
  faint: "#565c6b",
@@ -1684,7 +1720,7 @@ const PHASE_META = {
1684
1720
  },
1685
1721
  error: {
1686
1722
  label: "error",
1687
- icon: "✖",
1723
+ icon: "✘",
1688
1724
  color: ui.bad,
1689
1725
  kind: "static"
1690
1726
  },
@@ -1753,6 +1789,12 @@ const FILTER_LEVELS = [
1753
1789
  "debug",
1754
1790
  "trace"
1755
1791
  ];
1792
+ function Heading({ label, open }) {
1793
+ return /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, {
1794
+ color: ui.accent,
1795
+ bold: true
1796
+ }, open ? "▾" : "▸"), /* @__PURE__ */ React.createElement(Text, { color: ui.muted }, " ", label));
1797
+ }
1756
1798
  function Chip$1({ label, on, color, focused }) {
1757
1799
  return /* @__PURE__ */ React.createElement(Box, { marginRight: 1 }, on ? /* @__PURE__ */ React.createElement(Text, {
1758
1800
  color,
@@ -1764,15 +1806,18 @@ function Chip$1({ label, on, color, focused }) {
1764
1806
  underline: focused
1765
1807
  }, label));
1766
1808
  }
1767
- function FilterChips({ channels, enabledChannels, enabledLevels, cursor }) {
1809
+ function FilterChips({ channels, enabledChannels, enabledLevels, cursor, open }) {
1768
1810
  const allChannels = enabledChannels.size === 0;
1769
1811
  const allLevels = enabledLevels.size === 0;
1770
1812
  const channelFocus = focusedIn(cursor, "channels", channels.length);
1771
1813
  const levelFocus = focusedIn(cursor, "levels", FILTER_LEVELS.length);
1772
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, {
1773
- bold: true,
1774
- color: ui.heading
1775
- }, "- channels"), /* @__PURE__ */ React.createElement(Box, {
1814
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, open ? null : /* @__PURE__ */ React.createElement(Text, {
1815
+ dimColor: true,
1816
+ wrap: "truncate"
1817
+ }, "↕ resize to see filters"), /* @__PURE__ */ React.createElement(Heading, {
1818
+ label: "channels",
1819
+ open
1820
+ }), open ? /* @__PURE__ */ React.createElement(Box, {
1776
1821
  marginLeft: 2,
1777
1822
  flexWrap: "wrap"
1778
1823
  }, channels.map((channel, index) => /* @__PURE__ */ React.createElement(Chip$1, {
@@ -1781,10 +1826,10 @@ function FilterChips({ channels, enabledChannels, enabledLevels, cursor }) {
1781
1826
  on: allChannels || enabledChannels.has(channel),
1782
1827
  color: channelColor(channel),
1783
1828
  focused: channelFocus === index
1784
- }))), /* @__PURE__ */ React.createElement(Text, {
1785
- bold: true,
1786
- color: ui.heading
1787
- }, "- levels"), /* @__PURE__ */ React.createElement(Box, {
1829
+ }))) : null, /* @__PURE__ */ React.createElement(Heading, {
1830
+ label: "levels",
1831
+ open
1832
+ }), open ? /* @__PURE__ */ React.createElement(Box, {
1788
1833
  marginLeft: 2,
1789
1834
  flexWrap: "wrap"
1790
1835
  }, FILTER_LEVELS.map((level, index) => /* @__PURE__ */ React.createElement(Chip$1, {
@@ -1793,7 +1838,7 @@ function FilterChips({ channels, enabledChannels, enabledLevels, cursor }) {
1793
1838
  on: allLevels || enabledLevels.has(level),
1794
1839
  color: LEVEL_COLOR[level],
1795
1840
  focused: levelFocus === index
1796
- }))));
1841
+ }))) : null);
1797
1842
  }
1798
1843
 
1799
1844
  //#endregion
@@ -1849,17 +1894,16 @@ function applyAtCursor(ctx, channels, onChannel, onLevel) {
1849
1894
  const level = index === null ? void 0 : FILTER_LEVELS[index];
1850
1895
  if (level !== void 0) ctx.setEnabledLevels(onLevel(ctx.enabledLevels, level));
1851
1896
  }
1852
- function handleToggleMode(ctx) {
1853
- if (!ctx.showToggles) return false;
1897
+ function handleFilters(ctx) {
1898
+ if (!ctx.filtersOpen) return false;
1854
1899
  const channels = LogStore.instance.getChannels();
1855
1900
  const move = (dir) => ctx.setCursor(moveCursor(ctx.cursor, dir, channels.length, FILTER_LEVELS.length));
1856
- if (ctx.key.escape || ctx.key.return || ctx.input === "f") ctx.setShowToggles(false);
1857
- else if (ctx.key.leftArrow) move("left");
1901
+ if (ctx.key.leftArrow) move("left");
1858
1902
  else if (ctx.key.rightArrow) move("right");
1859
- else if (ctx.key.upArrow) move("up");
1860
- else if (ctx.key.downArrow) move("down");
1903
+ else if (ctx.key.tab) move("switch");
1861
1904
  else if (ctx.input === " ") applyAtCursor(ctx, channels, soloChannel, soloLevel);
1862
- else if (ctx.input === "t") applyAtCursor(ctx, channels, toggleChannel, toggleLevel);
1905
+ else if (ctx.input === "o") applyAtCursor(ctx, channels, toggleChannel, toggleLevel);
1906
+ else return false;
1863
1907
  return true;
1864
1908
  }
1865
1909
  function handleScroll(ctx) {
@@ -1890,10 +1934,6 @@ function handleActions(ctx) {
1890
1934
  store.beginRestart();
1891
1935
  ctx.onRestart?.();
1892
1936
  break;
1893
- case "f":
1894
- ctx.setCursor(INITIAL_CURSOR);
1895
- ctx.setShowToggles(true);
1896
- break;
1897
1937
  case "l":
1898
1938
  LogStore.instance.clear();
1899
1939
  ctx.scroll.toBottom();
@@ -1903,7 +1943,7 @@ function handleActions(ctx) {
1903
1943
  function dispatchHotkey(ctx) {
1904
1944
  if (handleQuitSignal(ctx)) return;
1905
1945
  if (handlePrompt(ctx)) return;
1906
- if (handleToggleMode(ctx)) return;
1946
+ if (handleFilters(ctx)) return;
1907
1947
  if (handleScroll(ctx)) return;
1908
1948
  handleActions(ctx);
1909
1949
  }
@@ -1919,75 +1959,27 @@ function LogHeader({ following, below }) {
1919
1959
  }
1920
1960
 
1921
1961
  //#endregion
1922
- //#region src/ui/components/CommandRefreshPrompt.tsx
1923
- function CommandRefreshPrompt({ files }) {
1924
- return /* @__PURE__ */ React.createElement(Box, {
1925
- borderStyle: "round",
1926
- borderColor: ui.warn,
1927
- flexDirection: "column",
1928
- paddingX: 1
1929
- }, /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, {
1930
- color: ui.warn,
1931
- bold: true
1932
- }, "Commands updated:")), files.map((file) => /* @__PURE__ */ React.createElement(Text, {
1933
- key: file,
1934
- color: ui.accent
1935
- }, "- ", file)), /* @__PURE__ */ React.createElement(Text, null, "Refresh commands? (y/n)"));
1936
- }
1937
-
1938
- //#endregion
1939
- //#region src/ui/components/ErrorDisplay.tsx
1940
- const STACK_PREVIEW_LINES = 6;
1941
- function ErrorDisplay({ error }) {
1942
- const frames = (error.stack?.split("\n") ?? []).slice(1);
1943
- const preview = frames.slice(0, STACK_PREVIEW_LINES);
1944
- const hidden = frames.length - preview.length;
1962
+ //#region src/ui/components/primitives/NotificationStack.tsx
1963
+ function NotificationStack({ notices }) {
1964
+ if (notices.length === 0) return null;
1945
1965
  return /* @__PURE__ */ React.createElement(Box, {
1946
- flexDirection: "column",
1947
- borderStyle: "round",
1948
- borderColor: ui.bad,
1949
- padding: 1
1950
- }, /* @__PURE__ */ React.createElement(Box, { marginTop: -1 }, /* @__PURE__ */ React.createElement(Text, {
1951
- color: ui.bad,
1952
- bold: true
1953
- }, "Error: ", error.name)), /* @__PURE__ */ React.createElement(Text, null, error.message), preview.length > 0 && /* @__PURE__ */ React.createElement(Box, {
1954
- marginTop: 1,
1966
+ flexShrink: 0,
1955
1967
  flexDirection: "column"
1956
- }, preview.map((line) => /* @__PURE__ */ React.createElement(Text, {
1957
- key: line,
1958
- dimColor: true,
1959
- wrap: "truncate"
1960
- }, line)), hidden > 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, `… ${hidden} more line${hidden === 1 ? "" : "s"}`)), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "press", " ", /* @__PURE__ */ React.createElement(Text, {
1961
- color: ui.warn,
1962
- bold: true
1963
- }, "r"), " ", "to restart")));
1964
- }
1965
-
1966
- //#endregion
1967
- //#region src/ui/components/RestartRequiredCard.tsx
1968
- function RestartRequiredCard() {
1969
- return /* @__PURE__ */ React.createElement(Box, {
1970
- borderStyle: "round",
1971
- borderColor: ui.warn,
1972
- flexDirection: "column",
1973
- paddingX: 1
1974
- }, /* @__PURE__ */ React.createElement(Text, {
1975
- color: ui.warn,
1976
- bold: true
1977
- }, "Restart required"), /* @__PURE__ */ React.createElement(Text, null, "A change needs a full restart. press", " ", /* @__PURE__ */ React.createElement(Text, {
1978
- color: ui.warn,
1979
- bold: true
1980
- }, "r"), " ", "to restart"));
1968
+ }, notices.map((notice) => /* @__PURE__ */ React.createElement(Fragment, { key: notice.key }, notice.card)));
1981
1969
  }
1982
1970
 
1983
1971
  //#endregion
1984
- //#region src/ui/components/primitives/NotificationStack.tsx
1985
- function NotificationStack({ error, restartRequired, prompt }) {
1986
- if (!error && !restartRequired && !prompt) return null;
1972
+ //#region src/ui/components/primitives/Rule.tsx
1973
+ function Rule() {
1987
1974
  return /* @__PURE__ */ React.createElement(Box, {
1988
1975
  flexShrink: 0,
1989
- flexDirection: "column"
1990
- }, error ? /* @__PURE__ */ React.createElement(ErrorDisplay, { error }) : null, restartRequired ? /* @__PURE__ */ React.createElement(RestartRequiredCard, null) : null, prompt ? /* @__PURE__ */ React.createElement(CommandRefreshPrompt, { files: [...prompt] }) : null);
1976
+ borderStyle: "single",
1977
+ borderTop: true,
1978
+ borderBottom: false,
1979
+ borderLeft: false,
1980
+ borderRight: false,
1981
+ borderDimColor: true
1982
+ });
1991
1983
  }
1992
1984
 
1993
1985
  //#endregion
@@ -2015,7 +2007,8 @@ function formatClock(ts) {
2015
2007
 
2016
2008
  //#endregion
2017
2009
  //#region src/ui/components/primitives/ScrollableLogView.tsx
2018
- const MIN_LOG_LINES = 3;
2010
+ const MIN_LOG_LINES = 5;
2011
+ const NO_ROOM = "Need more room for logs.";
2019
2012
  const DOT = "⏺";
2020
2013
  const BAR = "▌";
2021
2014
  const GUIDE = "│";
@@ -2066,23 +2059,18 @@ function ContinuationLine({ log, labelWidth }) {
2066
2059
  }, BAR), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, log.text));
2067
2060
  return /* @__PURE__ */ React.createElement(Text, { wrap: "truncate" }, " ".repeat(messageColumn(labelWidth) - 2), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, GUIDE), " ", log.text);
2068
2061
  }
2069
- function Rule() {
2070
- return /* @__PURE__ */ React.createElement(Box, {
2071
- flexShrink: 0,
2072
- borderStyle: "single",
2073
- borderTop: true,
2074
- borderBottom: false,
2075
- borderLeft: false,
2076
- borderRight: false,
2077
- borderDimColor: true
2078
- });
2079
- }
2080
2062
  function ScrollableLogView({ visible, viewportHeight, measured }) {
2081
2063
  if (!measured) return null;
2082
- if (viewportHeight < MIN_LOG_LINES) return /* @__PURE__ */ React.createElement(Text, {
2083
- color: "yellow",
2064
+ if (viewportHeight < MIN_LOG_LINES) return /* @__PURE__ */ React.createElement(Box, {
2065
+ flexGrow: 1,
2066
+ alignItems: "center",
2067
+ justifyContent: "center",
2068
+ overflow: "hidden"
2069
+ }, /* @__PURE__ */ React.createElement(Text, {
2070
+ color: ui.warn,
2071
+ bold: true,
2084
2072
  wrap: "truncate"
2085
- }, "Terminal too small to show logs.");
2073
+ }, NO_ROOM));
2086
2074
  const labelWidth = Math.max(1, LogStore.instance.getLabelWidth());
2087
2075
  return /* @__PURE__ */ React.createElement(Box, {
2088
2076
  flexDirection: "column",
@@ -2115,24 +2103,36 @@ function Banner({ version }) {
2115
2103
  }, "cord"), version === null ? null : /* @__PURE__ */ React.createElement(Text, { color: VERSION_COLOR }, " • v", version));
2116
2104
  }
2117
2105
 
2106
+ //#endregion
2107
+ //#region src/ui/components/primitives/BlinkDot.tsx
2108
+ const BLINK_MS = 530;
2109
+ function BlinkDot() {
2110
+ const { frame } = useAnimation({ interval: BLINK_MS });
2111
+ return /* @__PURE__ */ React.createElement(Text, { color: ui.bad }, frame % 2 === 0 ? "●" : " ");
2112
+ }
2113
+
2118
2114
  //#endregion
2119
2115
  //#region src/ui/components/StatusBadge.tsx
2120
- function Glyph({ phase }) {
2116
+ function Glyph({ phase, glyph }) {
2121
2117
  const meta = PHASE_META[phase];
2118
+ if (glyph === "live") return isStreaming(phase) ? /* @__PURE__ */ React.createElement(BlinkDot, null) : /* @__PURE__ */ React.createElement(Text, null, meta.icon);
2122
2119
  if (meta.kind === "spinner") return /* @__PURE__ */ React.createElement(Spinner, { type: "balloon2" });
2123
2120
  if (meta.kind === "arc") return /* @__PURE__ */ React.createElement(Spinner, { type: "toggle4" });
2124
2121
  return /* @__PURE__ */ React.createElement(Text, null, meta.icon);
2125
2122
  }
2126
- function StatusBadge({ phase }) {
2123
+ function StatusBadge({ phase, glyph = "phase" }) {
2127
2124
  const meta = PHASE_META[phase];
2128
2125
  return /* @__PURE__ */ React.createElement(Text, {
2129
2126
  color: meta.color,
2130
2127
  bold: true
2131
- }, /* @__PURE__ */ React.createElement(Glyph, { phase }), " ", meta.label);
2128
+ }, /* @__PURE__ */ React.createElement(Glyph, {
2129
+ phase,
2130
+ glyph
2131
+ }), " ", meta.label);
2132
2132
  }
2133
2133
 
2134
2134
  //#endregion
2135
- //#region src/ui/components/primitives/HotkeyBar.tsx
2135
+ //#region src/ui/components/primitives/Hotkeys.tsx
2136
2136
  function Hotkey({ keyLabel, action, enabled = true, highlight = false }) {
2137
2137
  const keyColor = !enabled ? ui.faint : highlight ? ui.warn : ui.accent;
2138
2138
  const actionColor = enabled ? ui.muted : ui.faint;
@@ -2146,8 +2146,8 @@ const RESTART_HINT_PHASES = new Set([
2146
2146
  "disconnected",
2147
2147
  "error"
2148
2148
  ]);
2149
- function DefaultKeys({ phase, interactive, following }) {
2150
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Hotkey, {
2149
+ function SessionKeys({ phase, interactive, following }) {
2150
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Hotkey, {
2151
2151
  keyLabel: "q",
2152
2152
  action: "quit"
2153
2153
  }), /* @__PURE__ */ React.createElement(Hotkey, {
@@ -2159,10 +2159,6 @@ function DefaultKeys({ phase, interactive, following }) {
2159
2159
  keyLabel: "d",
2160
2160
  action: "disconnect",
2161
2161
  enabled: interactive && isSessionLive(phase)
2162
- }), /* @__PURE__ */ React.createElement(Hotkey, {
2163
- keyLabel: "f",
2164
- action: "filters",
2165
- enabled: interactive
2166
2162
  }), /* @__PURE__ */ React.createElement(Hotkey, {
2167
2163
  keyLabel: "l",
2168
2164
  action: "clear",
@@ -2176,29 +2172,19 @@ function DefaultKeys({ phase, interactive, following }) {
2176
2172
  highlight: !following
2177
2173
  }));
2178
2174
  }
2179
- function HotkeyBar({ phase, interactive, mode, following }) {
2180
- return /* @__PURE__ */ React.createElement(Box, {
2181
- flexDirection: "column",
2182
- flexWrap: "wrap"
2183
- }, mode === "toggles" && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Hotkey, {
2175
+ function FilterKeys() {
2176
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Hotkey, {
2184
2177
  keyLabel: "←→",
2185
- action: "move"
2178
+ action: "select"
2186
2179
  }), /* @__PURE__ */ React.createElement(Hotkey, {
2187
- keyLabel: "↑↓",
2180
+ keyLabel: "tab",
2188
2181
  action: "group"
2189
2182
  }), /* @__PURE__ */ React.createElement(Hotkey, {
2190
2183
  keyLabel: "space",
2191
- action: "solo"
2184
+ action: "filter"
2192
2185
  }), /* @__PURE__ */ React.createElement(Hotkey, {
2193
- keyLabel: "t",
2186
+ keyLabel: "o",
2194
2187
  action: "toggle"
2195
- }), /* @__PURE__ */ React.createElement(Hotkey, {
2196
- keyLabel: "↵/esc",
2197
- action: "done"
2198
- })), mode === "default" && /* @__PURE__ */ React.createElement(DefaultKeys, {
2199
- phase,
2200
- interactive,
2201
- following
2202
2188
  }));
2203
2189
  }
2204
2190
 
@@ -2207,11 +2193,6 @@ function HotkeyBar({ phase, interactive, mode, following }) {
2207
2193
  const MAX_RAIL = 40;
2208
2194
  const META_LABEL_WIDTH = 5;
2209
2195
  const LOG_DIR = "logs/";
2210
- const BLINK_MS = 530;
2211
- function LiveDot() {
2212
- const { frame } = useAnimation({ interval: BLINK_MS });
2213
- return /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { color: ui.bad }, frame % 2 === 0 ? "●" : " "), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " live"));
2214
- }
2215
2196
  function Meta({ label, value }) {
2216
2197
  return /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, label.padEnd(META_LABEL_WIDTH)), value);
2217
2198
  }
@@ -2224,12 +2205,12 @@ function StatusBlock({ state, uptimeMs }) {
2224
2205
  value: LOG_DIR
2225
2206
  }));
2226
2207
  }
2227
- function Sidebar({ state, enabled, enabledLevels, uptimeMs, following, interactive, showToggles, cursor, width, ref }) {
2208
+ function Sidebar({ state, enabled, enabledLevels, uptimeMs, following, interactive, cursor, width, filtersOpen, ref }) {
2228
2209
  return /* @__PURE__ */ React.createElement(Box, {
2229
2210
  ref,
2230
2211
  flexDirection: "column",
2231
2212
  width: width ?? void 0,
2232
- maxWidth: MAX_RAIL,
2213
+ maxWidth: 40,
2233
2214
  flexShrink: 0,
2234
2215
  paddingX: 1,
2235
2216
  overflow: "hidden"
@@ -2247,27 +2228,57 @@ function Sidebar({ state, enabled, enabledLevels, uptimeMs, following, interacti
2247
2228
  channels: LogStore.instance.getChannels(),
2248
2229
  enabledChannels: enabled,
2249
2230
  enabledLevels,
2250
- cursor: showToggles ? cursor : null
2251
- })), /* @__PURE__ */ React.createElement(Box, {
2231
+ cursor,
2232
+ open: filtersOpen
2233
+ })), filtersOpen ? /* @__PURE__ */ React.createElement(Box, {
2252
2234
  flexShrink: 0,
2253
- marginTop: 1
2254
- }, /* @__PURE__ */ React.createElement(HotkeyBar, {
2235
+ marginTop: 1,
2236
+ flexDirection: "column"
2237
+ }, /* @__PURE__ */ React.createElement(FilterKeys, null), /* @__PURE__ */ React.createElement(Rule, null)) : null, /* @__PURE__ */ React.createElement(Box, {
2238
+ flexShrink: 0,
2239
+ marginTop: filtersOpen ? 0 : 1
2240
+ }, /* @__PURE__ */ React.createElement(SessionKeys, {
2255
2241
  phase: state.phase,
2256
2242
  interactive,
2257
- mode: showToggles ? "toggles" : "default",
2258
2243
  following
2259
2244
  })), /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }), /* @__PURE__ */ React.createElement(Box, {
2260
2245
  flexShrink: 0,
2261
2246
  justifyContent: "flex-end"
2262
- }, isStreaming(state.phase) ? /* @__PURE__ */ React.createElement(LiveDot, null) : /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "○ idle")));
2247
+ }, isStreaming(state.phase) ? /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(BlinkDot, null), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " live")) : /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "○ idle")));
2248
+ }
2249
+
2250
+ //#endregion
2251
+ //#region src/ui/components/primitives/StatusLine.tsx
2252
+ const HINT = "↕ resize for full ui";
2253
+ const HINT_COLUMNS = 64;
2254
+ /** The single row standing in for the rail once the terminal is too small to hold it. */
2255
+ function StatusLine({ state, notices, columns }) {
2256
+ const [top, ...rest] = notices;
2257
+ return /* @__PURE__ */ React.createElement(Box, {
2258
+ flexShrink: 0,
2259
+ justifyContent: "space-between"
2260
+ }, /* @__PURE__ */ React.createElement(Box, {
2261
+ flexShrink: 1,
2262
+ overflow: "hidden"
2263
+ }, /* @__PURE__ */ React.createElement(Text, { wrap: "truncate" }, /* @__PURE__ */ React.createElement(Banner, { version: null }), " ", /* @__PURE__ */ React.createElement(StatusBadge, {
2264
+ phase: state.phase,
2265
+ glyph: "live"
2266
+ }), top?.summary ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " · ") : null, top?.summary ? /* @__PURE__ */ React.createElement(Text, { color: ui.warn }, top.summary) : null, rest.length > 0 ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " · +", rest.length) : null)), /* @__PURE__ */ React.createElement(Box, {
2267
+ flexShrink: 0,
2268
+ marginLeft: 2
2269
+ }, top ? /* @__PURE__ */ React.createElement(Text, {
2270
+ bold: true,
2271
+ color: ui.accent
2272
+ }, top.action) : null, !top && columns >= HINT_COLUMNS ? /* @__PURE__ */ React.createElement(Text, { dimColor: true }, HINT) : null));
2263
2273
  }
2264
2274
 
2265
2275
  //#endregion
2266
2276
  //#region src/ui/layout/DevLayout.tsx
2267
2277
  function DevLayout(props) {
2268
- const { state, railRef, railWidth, logBoxRef, scroll, viewportHeight, measured } = props;
2269
- const { enabled, enabledLevels, showToggles, cursor, interactive, uptimeMs } = props;
2270
- return /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }, /* @__PURE__ */ React.createElement(Sidebar, {
2278
+ const { state, tier, notices, railRef, railWidth, logBoxRef, scroll, viewportHeight, measured } = props;
2279
+ const { columns, enabled, enabledLevels, cursor, interactive, uptimeMs } = props;
2280
+ const railed = tier === "full" || tier === "compact";
2281
+ return /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }, railed ? /* @__PURE__ */ React.createElement(Sidebar, {
2271
2282
  ref: railRef,
2272
2283
  state,
2273
2284
  enabled,
@@ -2275,10 +2286,10 @@ function DevLayout(props) {
2275
2286
  uptimeMs,
2276
2287
  following: scroll.following,
2277
2288
  interactive,
2278
- showToggles,
2279
2289
  cursor,
2280
- width: railWidth
2281
- }), /* @__PURE__ */ React.createElement(Box, {
2290
+ width: railWidth,
2291
+ filtersOpen: tier === "full"
2292
+ }) : null, /* @__PURE__ */ React.createElement(Box, {
2282
2293
  flexDirection: "column",
2283
2294
  flexGrow: 1,
2284
2295
  minWidth: 0,
@@ -2287,24 +2298,26 @@ function DevLayout(props) {
2287
2298
  borderTop: false,
2288
2299
  borderRight: false,
2289
2300
  borderBottom: false,
2290
- paddingLeft: 1,
2301
+ borderLeft: railed,
2302
+ paddingLeft: railed ? 1 : 0,
2291
2303
  overflow: "hidden"
2292
- }, /* @__PURE__ */ React.createElement(LogHeader, {
2304
+ }, railed ? null : /* @__PURE__ */ React.createElement(StatusLine, {
2305
+ state,
2306
+ notices,
2307
+ columns
2308
+ }), railed ? null : /* @__PURE__ */ React.createElement(Rule, null), /* @__PURE__ */ React.createElement(LogHeader, {
2293
2309
  following: scroll.following,
2294
2310
  below: scroll.below
2295
2311
  }), /* @__PURE__ */ React.createElement(Box, {
2296
2312
  ref: logBoxRef,
2297
2313
  flexGrow: 1,
2314
+ minHeight: 1,
2298
2315
  overflow: "hidden"
2299
2316
  }, /* @__PURE__ */ React.createElement(ScrollableLogView, {
2300
2317
  visible: scroll.visible,
2301
2318
  viewportHeight,
2302
2319
  measured
2303
- })), /* @__PURE__ */ React.createElement(NotificationStack, {
2304
- error: state.error,
2305
- restartRequired: state.restartRequired,
2306
- prompt: state.commandUpdatePrompt
2307
- })));
2320
+ })), railed ? /* @__PURE__ */ React.createElement(NotificationStack, { notices }) : null));
2308
2321
  }
2309
2322
 
2310
2323
  //#endregion
@@ -2349,6 +2362,110 @@ function rowKey(row) {
2349
2362
  return row.key;
2350
2363
  }
2351
2364
 
2365
+ //#endregion
2366
+ //#region src/ui/components/CommandRefreshPrompt.tsx
2367
+ function CommandRefreshPrompt({ files }) {
2368
+ return /* @__PURE__ */ React.createElement(Box, {
2369
+ borderStyle: "round",
2370
+ borderColor: ui.warn,
2371
+ flexDirection: "column",
2372
+ paddingX: 1
2373
+ }, /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, {
2374
+ color: ui.warn,
2375
+ bold: true
2376
+ }, "Commands updated:")), files.map((file) => /* @__PURE__ */ React.createElement(Text, {
2377
+ key: file,
2378
+ color: ui.accent
2379
+ }, "- ", file)), /* @__PURE__ */ React.createElement(Text, null, "Refresh commands? (y/n)"));
2380
+ }
2381
+
2382
+ //#endregion
2383
+ //#region src/ui/components/ErrorDisplay.tsx
2384
+ const STACK_PREVIEW_LINES = 6;
2385
+ function ErrorDisplay({ error }) {
2386
+ const frames = (error.stack?.split("\n") ?? []).slice(1);
2387
+ const preview = frames.slice(0, STACK_PREVIEW_LINES);
2388
+ const hidden = frames.length - preview.length;
2389
+ return /* @__PURE__ */ React.createElement(Box, {
2390
+ flexDirection: "column",
2391
+ borderStyle: "round",
2392
+ borderColor: ui.bad,
2393
+ paddingX: 1
2394
+ }, /* @__PURE__ */ React.createElement(Text, {
2395
+ color: ui.bad,
2396
+ bold: true
2397
+ }, "Error: ", error.name), /* @__PURE__ */ React.createElement(Text, null, error.message), preview.length > 0 && /* @__PURE__ */ React.createElement(Box, {
2398
+ marginTop: 1,
2399
+ flexDirection: "column"
2400
+ }, preview.map((line) => /* @__PURE__ */ React.createElement(Text, {
2401
+ key: line,
2402
+ dimColor: true,
2403
+ wrap: "truncate"
2404
+ }, line)), hidden > 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, `… ${hidden} more line${hidden === 1 ? "" : "s"}`)), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, null, "press", " ", /* @__PURE__ */ React.createElement(Text, {
2405
+ color: ui.warn,
2406
+ bold: true
2407
+ }, "r"), " ", "to restart")));
2408
+ }
2409
+
2410
+ //#endregion
2411
+ //#region src/ui/components/RestartRequiredCard.tsx
2412
+ function RestartRequiredCard() {
2413
+ return /* @__PURE__ */ React.createElement(Box, {
2414
+ borderStyle: "round",
2415
+ borderColor: ui.warn,
2416
+ flexDirection: "column",
2417
+ paddingX: 1
2418
+ }, /* @__PURE__ */ React.createElement(Text, {
2419
+ color: ui.warn,
2420
+ bold: true
2421
+ }, "Restart required"), /* @__PURE__ */ React.createElement(Text, null, "A change needs a full restart. press", " ", /* @__PURE__ */ React.createElement(Text, {
2422
+ color: ui.warn,
2423
+ bold: true
2424
+ }, "r"), " ", "to restart"));
2425
+ }
2426
+
2427
+ //#endregion
2428
+ //#region src/ui/notices.tsx
2429
+ const RESTART = "press r to restart";
2430
+ /** Every pending notice, ranked with the one that blocks a decision first. */
2431
+ function noticesOf(state) {
2432
+ const notices = [];
2433
+ if (state.commandUpdatePrompt) {
2434
+ const count = state.commandUpdatePrompt.length;
2435
+ notices.push({
2436
+ key: "commands",
2437
+ summary: `${count} command${count === 1 ? "" : "s"} updated`,
2438
+ action: "refresh? y/n",
2439
+ card: /* @__PURE__ */ React.createElement(CommandRefreshPrompt, { files: [...state.commandUpdatePrompt] })
2440
+ });
2441
+ }
2442
+ if (state.error) notices.push({
2443
+ key: "error",
2444
+ summary: state.error.message,
2445
+ action: RESTART,
2446
+ card: /* @__PURE__ */ React.createElement(ErrorDisplay, { error: state.error })
2447
+ });
2448
+ if (state.restartRequired) notices.push({
2449
+ key: "restart",
2450
+ summary: "",
2451
+ action: RESTART,
2452
+ card: /* @__PURE__ */ React.createElement(RestartRequiredCard, null)
2453
+ });
2454
+ return notices;
2455
+ }
2456
+
2457
+ //#endregion
2458
+ //#region src/ui/tier.ts
2459
+ const FULL_ROWS = 29;
2460
+ const COMPACT_ROWS = 20;
2461
+ const RAIL_COLUMNS = 80;
2462
+ function tierFor(rows, columns) {
2463
+ if (columns < 80) return "logs";
2464
+ if (rows >= 29) return "full";
2465
+ if (rows >= 20) return "compact";
2466
+ return "logs";
2467
+ }
2468
+
2352
2469
  //#endregion
2353
2470
  //#region src/ui/DevApp.tsx
2354
2471
  function DevApp(props) {
@@ -2357,30 +2474,19 @@ function DevApp(props) {
2357
2474
  const { rows, columns } = useWindowSize();
2358
2475
  const [enabled, setEnabled] = useState(() => /* @__PURE__ */ new Set());
2359
2476
  const [enabledLevels, setEnabledLevels] = useState(() => /* @__PURE__ */ new Set());
2360
- const [showToggles, setShowToggles] = useState(false);
2361
2477
  const [cursor, setCursor] = useState(INITIAL_CURSOR);
2362
2478
  const logBoxRef = useRef(null);
2363
- const [logBoxHeight, setLogBoxHeight] = useState(0);
2479
+ const logBoxHeight = useMeasuredHeight(logBoxRef);
2364
2480
  const railRef = useRef(null);
2365
2481
  const railWidth = useRailWidth(railRef, state.phase, rows, columns);
2482
+ const tier = tierFor(rows, columns);
2483
+ const notices = noticesOf(state);
2366
2484
  const logs = useLogs(enabled, enabledLevels);
2367
2485
  const logRows = useMemo(() => expandRows(logs), [logs]);
2368
2486
  const viewportHeight = Math.max(1, logBoxHeight);
2369
2487
  const scroll = useScroll(logRows, viewportHeight, rowKey);
2370
2488
  const uptimeMs = useUptime(state);
2371
2489
  const interactive = !state.isBusy || state.restartRequired;
2372
- useLayoutEffect(() => {
2373
- if (!logBoxRef.current) return;
2374
- const measured = measureElement(logBoxRef.current).height;
2375
- setLogBoxHeight((prev) => prev === measured ? prev : measured);
2376
- }, [
2377
- rows,
2378
- columns,
2379
- state.error,
2380
- state.restartRequired,
2381
- state.commandUpdatePrompt,
2382
- scroll.following
2383
- ]);
2384
2490
  useInput((input, key) => {
2385
2491
  dispatchHotkey({
2386
2492
  input,
@@ -2393,10 +2499,9 @@ function DevApp(props) {
2393
2499
  setEnabled,
2394
2500
  enabledLevels,
2395
2501
  setEnabledLevels,
2396
- showToggles,
2397
- setShowToggles,
2398
2502
  cursor,
2399
2503
  setCursor,
2504
+ filtersOpen: tier === "full",
2400
2505
  onQuit: props.onQuit,
2401
2506
  onDisconnect: props.onDisconnect,
2402
2507
  onRestart: props.onRestart,
@@ -2421,15 +2526,17 @@ function DevApp(props) {
2421
2526
  overflow: "hidden"
2422
2527
  }, /* @__PURE__ */ React.createElement(DevLayout, {
2423
2528
  state,
2529
+ tier,
2530
+ notices,
2424
2531
  railRef,
2425
2532
  railWidth,
2426
2533
  logBoxRef,
2427
2534
  scroll,
2428
2535
  viewportHeight,
2429
2536
  measured: logBoxHeight > 0,
2537
+ columns,
2430
2538
  enabled,
2431
2539
  enabledLevels,
2432
- showToggles,
2433
2540
  cursor,
2434
2541
  interactive,
2435
2542
  uptimeMs
@@ -2524,16 +2631,6 @@ var DevStore = class extends TypedEventEmitter {
2524
2631
  }
2525
2632
  };
2526
2633
 
2527
- //#endregion
2528
- //#region src/utils/SilentLogger.ts
2529
- const silentLogger = {
2530
- error: () => void 0,
2531
- warn: () => void 0,
2532
- info: () => void 0,
2533
- debug: () => void 0,
2534
- trace: () => void 0
2535
- };
2536
-
2537
2634
  //#endregion
2538
2635
  //#region src/commands/dev/runtime/HmrPlugin.ts
2539
2636
  const DEBOUNCE_MS = 250;
@@ -2992,10 +3089,8 @@ var DevRunner = class DevRunner {
2992
3089
  }
2993
3090
  static create(logger, store) {
2994
3091
  const moduleLoader = new RuntimeModuleLoader();
2995
- const locator = new ConfigLocator(logger);
2996
- const configLoader = new ConfigLoader(moduleLoader, logger);
2997
- const codegenLogger = new Logger("CLI:Codegen");
2998
- return new DevRunner(locator, configLoader, store, CodegenRunner.create(codegenLogger), codegenLogger);
3092
+ const codegenLogger = new Logger("Codegen", { channel: "cli" });
3093
+ return new DevRunner(new ConfigLocator(logger), new ConfigLoader(moduleLoader, logger), store, CodegenRunner.create(codegenLogger), codegenLogger);
2999
3094
  }
3000
3095
  async run() {
3001
3096
  if (this.isRunning) return;
@@ -3043,7 +3138,7 @@ var DevRunner = class DevRunner {
3043
3138
  async handleError(error) {
3044
3139
  this.store.setPhase("error");
3045
3140
  this.store.setError(Error.isError(error) ? error : new Error(String(error)));
3046
- this.store.setStatus("Error occurred. Press r to restart.");
3141
+ this.store.setStatus("Press r to restart.");
3047
3142
  this.store.setBusy(false);
3048
3143
  await this.waitForSignal();
3049
3144
  this.store.setBusy(true);
@@ -3097,9 +3192,9 @@ var DevCommand = class extends BaseCommand {
3097
3192
  runner;
3098
3193
  store;
3099
3194
  constructor() {
3100
- super("dev", "Run a Seedcord instance from the config file", "CLI:Dev");
3195
+ super("dev", "Run a Seedcord instance from the config file", "Dev");
3101
3196
  this.store = new DevStore();
3102
- this.runner = DevRunner.create(silentLogger, this.store);
3197
+ this.runner = DevRunner.create(this.logger, this.store);
3103
3198
  }
3104
3199
  register(program) {
3105
3200
  program.command(this.name).description(this.description).action(async () => {
@@ -3149,7 +3244,6 @@ var DevCommand = class extends BaseCommand {
3149
3244
 
3150
3245
  //#endregion
3151
3246
  //#region src/cli.ts
3152
- const LOGGER_LABEL = "seedcord CLI";
3153
3247
  async function main() {
3154
3248
  if (!process.env.ENV && !process.env.ENVIRONMENT && !process.env.NODE_ENV) process.env.NODE_ENV = "development";
3155
3249
  installNodeDefaults();
@@ -3161,7 +3255,7 @@ async function main() {
3161
3255
  await program.parseAsync(process.argv);
3162
3256
  }
3163
3257
  main().catch((error) => {
3164
- new Logger(LOGGER_LABEL).error("Unexpected CLI error", error);
3258
+ new Logger("CLI", { channel: "cli" }).error("Unexpected CLI error", error);
3165
3259
  process.exit(1);
3166
3260
  });
3167
3261