skillmux 0.1.4 → 0.1.6

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.
@@ -21,7 +21,7 @@ import {
21
21
  runRemove,
22
22
  runScan,
23
23
  scanAgentSkills
24
- } from "./chunk-EEIOA7GC.js";
24
+ } from "./chunk-OY3C7VIL.js";
25
25
 
26
26
  // src/tui/launch-tui.tsx
27
27
  import { render } from "ink";
@@ -445,6 +445,7 @@ function buildAgentRows(input) {
445
445
  ...agentOverride?.skillsDirectoryPath === void 0 ? {} : { overrideSkillsDirectoryPath: agentOverride.skillsDirectoryPath },
446
446
  ...agentOverride?.supportedPlatforms === void 0 ? {} : { overrideSupportedPlatforms: [...agentOverride.supportedPlatforms] },
447
447
  ...agentOverride?.enabledByDefault === void 0 ? {} : { overrideEnabledByDefault: agentOverride.enabledByDefault },
448
+ autoDiscovered: agentOverride?.autoDiscovered === true ? true : void 0,
448
449
  discovery: agent.discovery,
449
450
  exists: agent.exists,
450
451
  supported: agent.supportedOnPlatform,
@@ -1528,26 +1529,78 @@ function updateTuiState(state, event) {
1528
1529
  return readyState;
1529
1530
  }
1530
1531
 
1531
- // src/tui/components/AgentList.tsx
1532
- import { Box, Text } from "ink";
1533
- import { jsx, jsxs } from "react/jsx-runtime";
1534
- function statusMarker(agent) {
1535
- if (!agent.supported) {
1536
- return "!";
1532
+ // src/tui/theme.ts
1533
+ import React from "react";
1534
+ var nord0 = "#2e3440";
1535
+ var nord1 = "#3b4252";
1536
+ var nord3 = "#4c566a";
1537
+ var nord4 = "#d8dee9";
1538
+ var nord6 = "#eceff4";
1539
+ var nord8 = "#88c0d0";
1540
+ var nord9 = "#81a1c1";
1541
+ var nord11 = "#bf616a";
1542
+ var nord13 = "#ebcb8b";
1543
+ var nord14 = "#a3be8c";
1544
+ var nord15 = "#b48ead";
1545
+ var nordTheme = {
1546
+ fg: { default: nord4, muted: nord3, emphasis: nord6 },
1547
+ bg: { base: nord0, surface: nord1, overlay: nord1, selection: nord9 },
1548
+ accent: { primary: nord9, secondary: nord15 },
1549
+ status: { success: nord14, warning: nord13, error: nord11, info: nord8 },
1550
+ border: { default: nord3, focused: nord9 }
1551
+ };
1552
+ var fallbackTheme = {
1553
+ fg: { default: "white", muted: "gray", emphasis: "white" },
1554
+ bg: {
1555
+ base: "black",
1556
+ surface: "black",
1557
+ overlay: "black",
1558
+ selection: "cyan"
1559
+ },
1560
+ accent: { primary: "cyan", secondary: "magenta" },
1561
+ status: { success: "green", warning: "yellow", error: "red", info: "cyan" },
1562
+ border: { default: "gray", focused: "cyan" }
1563
+ };
1564
+ function detectColorLevel() {
1565
+ if (process.env.NO_COLOR !== void 0) {
1566
+ return "none";
1537
1567
  }
1538
- if (!agent.exists) {
1539
- return "?";
1568
+ const colorTerm = process.env.COLORTERM;
1569
+ if (colorTerm === "truecolor" || colorTerm === "24bit") {
1570
+ return "truecolor";
1540
1571
  }
1541
- return "*";
1542
- }
1543
- function statusColor(agent) {
1544
- if (!agent.supported) {
1545
- return "red";
1572
+ const term = process.env.TERM ?? "";
1573
+ if (term.includes("256color")) {
1574
+ return "256";
1546
1575
  }
1547
- if (!agent.exists || agent.issueCount > 0) {
1548
- return "yellow";
1576
+ return "16";
1577
+ }
1578
+ function resolveTheme() {
1579
+ const colorLevel = detectColorLevel();
1580
+ if (colorLevel === "none" || colorLevel === "16") {
1581
+ return fallbackTheme;
1549
1582
  }
1550
- return "green";
1583
+ return nordTheme;
1584
+ }
1585
+ var ThemeContext = React.createContext(nordTheme);
1586
+ function useTheme() {
1587
+ return React.useContext(ThemeContext);
1588
+ }
1589
+ var ThemeProvider = ThemeContext.Provider;
1590
+
1591
+ // src/tui/components/AgentList.tsx
1592
+ import { Box, Text } from "ink";
1593
+ import { jsx, jsxs } from "react/jsx-runtime";
1594
+ function statusColor(agent, theme) {
1595
+ if (!agent.supported) return theme.status.error;
1596
+ if (!agent.exists || agent.issueCount > 0) return theme.status.warning;
1597
+ return theme.status.success;
1598
+ }
1599
+ function statusLabel(agent) {
1600
+ if (!agent.supported) return "!";
1601
+ if (!agent.exists) return "?";
1602
+ if (agent.issueCount > 0) return "*";
1603
+ return "*";
1551
1604
  }
1552
1605
  function AgentList({
1553
1606
  agents,
@@ -1557,20 +1610,23 @@ function AgentList({
1557
1610
  width = 24,
1558
1611
  height = 18
1559
1612
  }) {
1613
+ const theme = useTheme();
1560
1614
  const emptyMessage = searchQuery !== void 0 && searchQuery.trim().length > 0 ? "No matching agents" : "No agents found";
1561
1615
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width, height, children: [
1562
- /* @__PURE__ */ jsx(Text, { bold: true, color: focused ? "cyan" : void 0, children: "Agents" }),
1616
+ /* @__PURE__ */ jsx(Text, { bold: true, color: focused ? theme.fg.emphasis : theme.fg.muted, children: "Agents" }),
1563
1617
  agents.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: emptyMessage }) : agents.map((agent) => {
1564
- const selected = agent.id === selectedAgentId;
1565
- const selectionPrefix = selected ? ">" : " ";
1566
- return /* @__PURE__ */ jsxs(Text, { inverse: selected, children: [
1567
- /* @__PURE__ */ jsx(Text, { color: statusColor(agent), children: statusMarker(agent) }),
1568
- /* @__PURE__ */ jsxs(Text, { children: [
1569
- selectionPrefix,
1618
+ const isSelected = agent.id === selectedAgentId;
1619
+ const isActive = isSelected && focused;
1620
+ const prefix = isActive ? ">" : " ";
1621
+ return /* @__PURE__ */ jsx(Text, { children: /* @__PURE__ */ jsxs(Text, { backgroundColor: isSelected ? theme.bg.selection : void 0, children: [
1622
+ /* @__PURE__ */ jsx(Text, { color: statusColor(agent, theme), children: statusLabel(agent) }),
1623
+ /* @__PURE__ */ jsxs(Text, { color: isSelected ? theme.fg.emphasis : theme.fg.default, children: [
1624
+ " ",
1625
+ prefix,
1570
1626
  " ",
1571
1627
  agent.name
1572
1628
  ] })
1573
- ] }, agent.id);
1629
+ ] }) }, agent.id);
1574
1630
  })
1575
1631
  ] });
1576
1632
  }
@@ -1607,18 +1663,17 @@ function confirmationDetails(modal) {
1607
1663
  return `${modal.unmanagedCount} unmanaged skills will be moved under SkillMux management.`;
1608
1664
  }
1609
1665
  function ConfirmDialog({ modal }) {
1666
+ const theme = useTheme();
1667
+ const isRemove = modal.kind === "confirm-remove" || modal.kind === "confirm-remove-agent";
1668
+ const titleColor = isRemove ? theme.status.warning : theme.status.info;
1610
1669
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: confirmDialogHeight, children: [
1611
- /* @__PURE__ */ jsx2(
1612
- Text2,
1613
- {
1614
- bold: true,
1615
- color: modal.kind === "confirm-remove" || modal.kind === "confirm-remove-agent" ? "yellow" : "cyan",
1616
- children: "Confirm"
1617
- }
1618
- ),
1619
- /* @__PURE__ */ jsx2(Text2, { children: confirmationText(modal) }),
1620
- confirmationDetails(modal) === null ? null : /* @__PURE__ */ jsx2(Text2, { children: confirmationDetails(modal) }),
1621
- /* @__PURE__ */ jsx2(Text2, { children: "[y] confirm [Esc] cancel" })
1670
+ /* @__PURE__ */ jsx2(Text2, { bold: true, color: titleColor, children: "Confirm" }),
1671
+ /* @__PURE__ */ jsx2(Text2, { color: theme.fg.default, children: confirmationText(modal) }),
1672
+ confirmationDetails(modal) === null ? null : /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: confirmationDetails(modal) }),
1673
+ /* @__PURE__ */ jsxs2(Text2, { children: [
1674
+ /* @__PURE__ */ jsx2(Text2, { bold: true, color: theme.status.success, children: "[y] confirm" }),
1675
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " [Esc] cancel" })
1676
+ ] })
1622
1677
  ] });
1623
1678
  }
1624
1679
 
@@ -1640,17 +1695,18 @@ function DoctorDialog({
1640
1695
  width = 72,
1641
1696
  height = 14
1642
1697
  }) {
1698
+ const theme = useTheme();
1643
1699
  if (modal.status === "loading") {
1644
1700
  return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", width, height, children: [
1645
- /* @__PURE__ */ jsx3(Text3, { bold: true, children: "Doctor" }),
1646
- /* @__PURE__ */ jsx3(Text3, { children: "Loading doctor diagnostics..." }),
1701
+ /* @__PURE__ */ jsx3(Text3, { bold: true, color: theme.fg.emphasis, children: "Doctor" }),
1702
+ /* @__PURE__ */ jsx3(Text3, { color: theme.fg.muted, children: "Loading doctor diagnostics..." }),
1647
1703
  /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "[Esc] close" })
1648
1704
  ] });
1649
1705
  }
1650
1706
  if (modal.status === "error") {
1651
1707
  return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", width, height, children: [
1652
- /* @__PURE__ */ jsx3(Text3, { bold: true, children: "Doctor" }),
1653
- /* @__PURE__ */ jsx3(Text3, { color: "red", children: modal.errorMessage }),
1708
+ /* @__PURE__ */ jsx3(Text3, { bold: true, color: theme.fg.emphasis, children: "Doctor" }),
1709
+ /* @__PURE__ */ jsx3(Text3, { color: theme.status.error, children: modal.errorMessage }),
1654
1710
  /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "[Esc] close" })
1655
1711
  ] });
1656
1712
  }
@@ -1660,12 +1716,12 @@ function DoctorDialog({
1660
1716
  const clampedOffset = Math.min(Math.max(scrollOffset, 0), maxOffset);
1661
1717
  const visibleIssues = issues.slice(clampedOffset, clampedOffset + maxIssues);
1662
1718
  return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", width, height, children: [
1663
- /* @__PURE__ */ jsx3(Text3, { bold: true, children: "Doctor" }),
1719
+ /* @__PURE__ */ jsx3(Text3, { bold: true, color: theme.fg.emphasis, children: "Doctor" }),
1664
1720
  /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: issues.length === 0 ? "No doctor issues found." : `${issues.length} issue(s) found` }),
1665
1721
  issues.length === 0 ? null : /* @__PURE__ */ jsxs3(Fragment, { children: [
1666
1722
  visibleIssues.map((issue) => /* @__PURE__ */ jsxs3(Text3, { children: [
1667
- /* @__PURE__ */ jsx3(Text3, { color: issue.severity === "error" ? "red" : "yellow", children: "! " }),
1668
- /* @__PURE__ */ jsxs3(Text3, { children: [
1723
+ /* @__PURE__ */ jsx3(Text3, { color: issue.severity === "error" ? theme.status.error : theme.status.warning, children: "! " }),
1724
+ /* @__PURE__ */ jsxs3(Text3, { color: theme.fg.default, children: [
1669
1725
  issueLabel(issue),
1670
1726
  " - ",
1671
1727
  issue.message,
@@ -1689,26 +1745,18 @@ function DoctorDialog({
1689
1745
  import { Box as Box4, Text as Text4 } from "ink";
1690
1746
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1691
1747
  function compactPath(value, maxLength) {
1692
- if (value.length <= maxLength) {
1693
- return value;
1694
- }
1748
+ if (value.length <= maxLength) return value;
1695
1749
  const separator = value.includes("\\") ? "\\" : "/";
1696
1750
  const parts = value.split(/[\\/]+/).filter((part) => part.length > 0);
1697
1751
  let suffix = parts.at(-1) ?? value;
1698
1752
  for (let index = parts.length - 2; index >= 0; index -= 1) {
1699
1753
  const candidate = `${parts[index]}${separator}${suffix}`;
1700
- if (`...${separator}${candidate}`.length > maxLength) {
1701
- break;
1702
- }
1754
+ if (`...${separator}${candidate}`.length > maxLength) break;
1703
1755
  suffix = candidate;
1704
1756
  }
1705
1757
  const shortened = `...${separator}${suffix}`;
1706
- if (shortened.length <= maxLength) {
1707
- return shortened;
1708
- }
1709
- if (maxLength <= 3) {
1710
- return ".".repeat(maxLength);
1711
- }
1758
+ if (shortened.length <= maxLength) return shortened;
1759
+ if (maxLength <= 3) return ".".repeat(maxLength);
1712
1760
  return `...${suffix.slice(-(maxLength - 3))}`;
1713
1761
  }
1714
1762
  function detailLines(skill) {
@@ -1756,9 +1804,10 @@ function DetailPane({
1756
1804
  width = 28,
1757
1805
  height = 18
1758
1806
  }) {
1807
+ const theme = useTheme();
1759
1808
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", width, height, children: [
1760
- /* @__PURE__ */ jsx4(Text4, { bold: true, children: "Detail" }),
1761
- selectedAgent === null ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "Select an agent" }) : /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
1809
+ /* @__PURE__ */ jsx4(Text4, { bold: true, color: theme.fg.emphasis, children: "Detail" }),
1810
+ selectedAgent === null ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "Select an agent" }) : /* @__PURE__ */ jsxs4(Text4, { color: theme.fg.muted, children: [
1762
1811
  "Agent: ",
1763
1812
  selectedAgent.name
1764
1813
  ] }),
@@ -1770,11 +1819,12 @@ function DetailPane({
1770
1819
  const valueWidth = Math.max(width - (label.length + 2), 8);
1771
1820
  const renderedValue = compact ? compactPath(value, valueWidth) : value;
1772
1821
  return /* @__PURE__ */ jsxs4(Text4, { children: [
1773
- /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
1822
+ /* @__PURE__ */ jsxs4(Text4, { bold: true, color: theme.accent.primary, children: [
1774
1823
  label,
1775
- ": "
1824
+ ":",
1825
+ " "
1776
1826
  ] }),
1777
- /* @__PURE__ */ jsx4(Text4, { children: renderedValue })
1827
+ /* @__PURE__ */ jsx4(Text4, { color: theme.fg.default, children: renderedValue })
1778
1828
  ] }, label);
1779
1829
  })
1780
1830
  ] });
@@ -1782,17 +1832,16 @@ function DetailPane({
1782
1832
 
1783
1833
  // src/tui/components/Footer.tsx
1784
1834
  import { Box as Box5, Text as Text5 } from "ink";
1785
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1786
- var agentLegend = "Agent icons: * ready yellow * issues ? missing ! unsupported";
1787
- var skillLegend = "Skill markers: \u25CF enabled \u25CB disabled ? unmanaged ! issue";
1835
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1788
1836
  function Footer({ actions, search }) {
1837
+ const theme = useTheme();
1789
1838
  const shortcuts = [
1790
1839
  actions.addAgent ? "[n]add agent" : null,
1791
1840
  actions.editAgent ? "[e]edit agent" : null,
1792
1841
  actions.removeAgent ? "[X]remove agent" : null,
1793
1842
  actions.importSkill ? "[i]import" : null,
1794
1843
  actions.doctor ? "[d]doctor" : null,
1795
- "[Left/Right]focus",
1844
+ "\u2190\u2192 focus",
1796
1845
  actions.toggle ? "[Space]toggle" : null,
1797
1846
  actions.adopt ? "[a]adopt" : null,
1798
1847
  actions.adoptAll ? "[Shift+A]adopt all" : null,
@@ -1801,46 +1850,90 @@ function Footer({ actions, search }) {
1801
1850
  actions.help ? "[?]help" : null,
1802
1851
  "[q]quit"
1803
1852
  ].filter((shortcut) => shortcut !== null);
1804
- return /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", height: 3, children: search === null ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1805
- /* @__PURE__ */ jsx5(Text5, { children: shortcuts.join(" ") }),
1806
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: agentLegend }),
1807
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: skillLegend })
1808
- ] }) : /* @__PURE__ */ jsxs5(Text5, { children: [
1809
- /* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "/" }),
1810
- /* @__PURE__ */ jsx5(Text5, { children: search.query }),
1811
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " [Enter]keep [Esc]cancel" })
1812
- ] }) });
1853
+ const legendParts = [
1854
+ { symbol: "\u25CF", label: "enabled", color: theme.status.success },
1855
+ { symbol: "\u25CB", label: "disabled", color: theme.fg.muted },
1856
+ { symbol: "?", label: "unmanaged", color: theme.status.warning },
1857
+ { symbol: "!", label: "issue", color: theme.status.error }
1858
+ ];
1859
+ if (search !== null) {
1860
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", height: 3, children: [
1861
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1862
+ /* @__PURE__ */ jsx5(Text5, { color: theme.accent.primary, children: "/" }),
1863
+ /* @__PURE__ */ jsx5(Text5, { color: theme.fg.default, children: search.query }),
1864
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " [Enter]keep [Esc]cancel" })
1865
+ ] }),
1866
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: legendParts.map((p, i) => /* @__PURE__ */ jsxs5(Text5, { children: [
1867
+ /* @__PURE__ */ jsxs5(Text5, { color: p.color, children: [
1868
+ p.symbol,
1869
+ " ",
1870
+ p.label
1871
+ ] }),
1872
+ i < legendParts.length - 1 ? " " : ""
1873
+ ] }, p.label)) })
1874
+ ] });
1875
+ }
1876
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", height: 3, children: [
1877
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: shortcuts.join(" ") }),
1878
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1879
+ "SkillMux ",
1880
+ "\xB7",
1881
+ " [j/k]move ",
1882
+ "\xB7",
1883
+ " [g/G]top/bottom ",
1884
+ "\xB7",
1885
+ " [/]search"
1886
+ ] }),
1887
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: legendParts.map((p, i) => /* @__PURE__ */ jsxs5(Text5, { children: [
1888
+ /* @__PURE__ */ jsxs5(Text5, { color: p.color, children: [
1889
+ p.symbol,
1890
+ " ",
1891
+ p.label
1892
+ ] }),
1893
+ i < legendParts.length - 1 ? " \xB7 " : ""
1894
+ ] }, p.label)) })
1895
+ ] });
1813
1896
  }
1814
1897
 
1815
1898
  // src/tui/components/HelpOverlay.tsx
1816
1899
  import { Box as Box6, Text as Text6 } from "ink";
1817
1900
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1818
1901
  function HelpOverlay() {
1902
+ const theme = useTheme();
1819
1903
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", height: 8, children: [
1820
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Help" }),
1821
- /* @__PURE__ */ jsxs6(Text6, { children: [
1822
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Navigation" }),
1823
- /* @__PURE__ */ jsx6(Text6, { children: ": Left/Right switch panels, j/k or Up/Down move, g/G jump." })
1824
- ] }),
1904
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.fg.emphasis, children: "Help" }),
1825
1905
  /* @__PURE__ */ jsxs6(Text6, { children: [
1826
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Actions" }),
1827
- /* @__PURE__ */ jsx6(Text6, { children: ": Space toggles, a adopts, Shift+A current-agent bulk adopt, r removes, s scans, n add agent, e edit selected override, X remove selected override, i import, d doctor." })
1906
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent.primary, children: "Navigation" }),
1907
+ /* @__PURE__ */ jsx6(Text6, { color: theme.fg.default, children: ": Left/Right switch panels, j/k or Up/Down move, g/G jump." })
1828
1908
  ] }),
1829
1909
  /* @__PURE__ */ jsxs6(Text6, { children: [
1830
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Search" }),
1831
- /* @__PURE__ */ jsx6(Text6, { children: ": / filters the focused list, Enter keeps the result, Esc cancels." })
1910
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent.primary, children: "Actions" }),
1911
+ /* @__PURE__ */ jsx6(Text6, { color: theme.fg.default, children: ": Space toggles, a adopts, Shift+A current-agent bulk adopt, r removes, s scans, n add agent, e edit selected override, X remove selected override, i import, d doctor." })
1832
1912
  ] }),
1833
1913
  /* @__PURE__ */ jsxs6(Text6, { children: [
1834
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Agent icons" }),
1835
- /* @__PURE__ */ jsx6(Text6, { children: ": * ready, yellow * issues, ? missing, ! unsupported." })
1914
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent.primary, children: "Search" }),
1915
+ /* @__PURE__ */ jsx6(Text6, { color: theme.fg.default, children: ": / filters the focused list, Enter keeps the result, Esc cancels." })
1836
1916
  ] }),
1837
1917
  /* @__PURE__ */ jsxs6(Text6, { children: [
1838
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Skill markers" }),
1839
- /* @__PURE__ */ jsx6(Text6, { children: ": \u25CF enabled, \u25CB disabled, ? unmanaged, ! issue." })
1918
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent.primary, children: "Skill markers" }),
1919
+ /* @__PURE__ */ jsx6(Text6, { color: theme.fg.default, children: ": " }),
1920
+ /* @__PURE__ */ jsxs6(Text6, { color: theme.status.success, children: [
1921
+ "\u25CF",
1922
+ " enabled"
1923
+ ] }),
1924
+ /* @__PURE__ */ jsx6(Text6, { color: theme.fg.default, children: " " }),
1925
+ /* @__PURE__ */ jsxs6(Text6, { color: theme.fg.muted, children: [
1926
+ "\u25CB",
1927
+ " disabled"
1928
+ ] }),
1929
+ /* @__PURE__ */ jsx6(Text6, { color: theme.fg.default, children: " " }),
1930
+ /* @__PURE__ */ jsx6(Text6, { color: theme.status.warning, children: "? unmanaged" }),
1931
+ /* @__PURE__ */ jsx6(Text6, { color: theme.fg.default, children: " " }),
1932
+ /* @__PURE__ */ jsx6(Text6, { color: theme.status.error, children: "! issue" })
1840
1933
  ] }),
1841
1934
  /* @__PURE__ */ jsxs6(Text6, { children: [
1842
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Safety" }),
1843
- /* @__PURE__ */ jsx6(Text6, { children: ": Toggle, adopt, remove, and scan can update SkillMux state and agent links." })
1935
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent.primary, children: "Safety" }),
1936
+ /* @__PURE__ */ jsx6(Text6, { color: theme.fg.default, children: ": Toggle, adopt, remove, and scan can update SkillMux state and agent links." })
1844
1937
  ] })
1845
1938
  ] });
1846
1939
  }
@@ -1852,36 +1945,60 @@ var platformOptions = ["win32", "linux", "darwin"];
1852
1945
  function checkbox(value) {
1853
1946
  return value ? "[x]" : "[ ]";
1854
1947
  }
1855
- function renderTextField(label, value, active) {
1856
- return /* @__PURE__ */ jsxs7(Text7, { inverse: active, children: [
1857
- /* @__PURE__ */ jsxs7(Text7, { bold: true, children: [
1948
+ function renderTextField(label, value, active, theme) {
1949
+ if (active) {
1950
+ return /* @__PURE__ */ jsxs7(Text7, { backgroundColor: theme.bg.selection, children: [
1951
+ /* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.fg.emphasis, children: [
1952
+ label,
1953
+ ": "
1954
+ ] }),
1955
+ /* @__PURE__ */ jsx7(Text7, { color: theme.fg.emphasis, children: value.length > 0 ? value : " " })
1956
+ ] }, label);
1957
+ }
1958
+ return /* @__PURE__ */ jsxs7(Text7, { children: [
1959
+ /* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accent.primary, children: [
1858
1960
  label,
1859
1961
  ": "
1860
1962
  ] }),
1861
- /* @__PURE__ */ jsx7(Text7, { children: value.length > 0 ? value : " " })
1963
+ /* @__PURE__ */ jsx7(Text7, { color: theme.fg.default, children: value.length > 0 ? value : " " })
1862
1964
  ] }, label);
1863
1965
  }
1864
- function renderBooleanField(label, value, active) {
1865
- return /* @__PURE__ */ jsxs7(Text7, { inverse: active, children: [
1866
- /* @__PURE__ */ jsxs7(Text7, { bold: true, children: [
1966
+ function renderBooleanField(label, value, active, theme) {
1967
+ if (active) {
1968
+ return /* @__PURE__ */ jsxs7(Text7, { backgroundColor: theme.bg.selection, children: [
1969
+ /* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.fg.emphasis, children: [
1970
+ label,
1971
+ ": "
1972
+ ] }),
1973
+ /* @__PURE__ */ jsx7(Text7, { color: theme.fg.emphasis, children: checkbox(value) })
1974
+ ] }, label);
1975
+ }
1976
+ return /* @__PURE__ */ jsxs7(Text7, { children: [
1977
+ /* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accent.primary, children: [
1867
1978
  label,
1868
1979
  ": "
1869
1980
  ] }),
1870
- /* @__PURE__ */ jsx7(Text7, { children: checkbox(value) })
1981
+ /* @__PURE__ */ jsx7(Text7, { color: theme.fg.default, children: checkbox(value) })
1871
1982
  ] }, label);
1872
1983
  }
1873
- function renderPlatformField(selectedPlatforms, activePlatformIndex, active) {
1984
+ function renderPlatformField(selectedPlatforms, activePlatformIndex, active, theme) {
1874
1985
  return platformOptions.map((platform, index) => {
1875
1986
  const selected = selectedPlatforms.includes(platform);
1876
1987
  const isCurrent = active && index === activePlatformIndex;
1877
- return /* @__PURE__ */ jsxs7(Text7, { inverse: isCurrent, children: [
1878
- /* @__PURE__ */ jsx7(Text7, { children: isCurrent ? "> " : " " }),
1879
- /* @__PURE__ */ jsxs7(Text7, { children: [
1988
+ if (isCurrent) {
1989
+ return /* @__PURE__ */ jsx7(Text7, { backgroundColor: theme.bg.selection, children: /* @__PURE__ */ jsxs7(Text7, { color: theme.fg.emphasis, children: [
1990
+ "> ",
1880
1991
  checkbox(selected),
1881
- " "
1882
- ] }),
1883
- /* @__PURE__ */ jsx7(Text7, { children: platform })
1884
- ] }, platform);
1992
+ " ",
1993
+ platform
1994
+ ] }) }, platform);
1995
+ }
1996
+ return /* @__PURE__ */ jsx7(Text7, { children: /* @__PURE__ */ jsxs7(Text7, { color: selected ? theme.status.success : theme.fg.muted, children: [
1997
+ " ",
1998
+ checkbox(selected),
1999
+ " ",
2000
+ platform
2001
+ ] }) }, platform);
1885
2002
  });
1886
2003
  }
1887
2004
  function FormDialog({
@@ -1891,89 +2008,94 @@ function FormDialog({
1891
2008
  width = 72,
1892
2009
  height = 14
1893
2010
  }) {
2011
+ const theme = useTheme();
1894
2012
  const activeField = fieldIndex;
1895
- const submitFieldIndex = modal.kind === "import" ? 2 : 6;
1896
2013
  if (modal.kind === "import") {
2014
+ const submitFieldIndex2 = 2;
1897
2015
  return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", width, height, children: [
1898
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: "Import skill" }),
1899
- modal.form.error === null ? null : /* @__PURE__ */ jsx7(Text7, { color: "red", children: modal.form.error }),
2016
+ /* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.fg.emphasis, children: "Import skill" }),
2017
+ modal.form.error === null ? null : /* @__PURE__ */ jsx7(Text7, { color: theme.status.error, children: modal.form.error }),
1900
2018
  renderTextField(
1901
2019
  "Source path",
1902
2020
  modal.form.values.sourcePath,
1903
- activeField === 0
2021
+ activeField === 0,
2022
+ theme
1904
2023
  ),
1905
2024
  renderTextField(
1906
2025
  "Skill name",
1907
2026
  modal.form.values.skillName,
1908
- activeField === 1
2027
+ activeField === 1,
2028
+ theme
1909
2029
  ),
1910
- /* @__PURE__ */ jsx7(Text7, { inverse: activeField === submitFieldIndex, children: "Submit" }),
2030
+ /* @__PURE__ */ jsx7(Text7, { children: activeField === submitFieldIndex2 ? /* @__PURE__ */ jsx7(Text7, { backgroundColor: theme.bg.selection, children: /* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.fg.emphasis, children: "Submit" }) }) : /* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.accent.primary, children: "Submit" }) }),
1911
2031
  /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "[Up/Down] move [Enter] submit selected row [Esc] cancel" })
1912
2032
  ] });
1913
2033
  }
1914
2034
  const title = modal.kind === "add-agent" ? "Add agent" : `Edit agent ${modal.agentId}`;
1915
2035
  const fields = modal.kind === "add-agent" ? [
1916
- renderTextField("Agent id", modal.form.values.id, activeField === 0),
1917
- renderTextField("Root path", modal.form.values.root, activeField === 1),
1918
- renderTextField("Skills path", modal.form.values.skills, activeField === 2),
1919
- renderTextField("Display name", modal.form.values.name, activeField === 3)
2036
+ renderTextField("Agent id", modal.form.values.id, activeField === 0, theme),
2037
+ renderTextField("Root path", modal.form.values.root, activeField === 1, theme),
2038
+ renderTextField("Skills path", modal.form.values.skills, activeField === 2, theme),
2039
+ renderTextField("Display name", modal.form.values.name, activeField === 3, theme)
1920
2040
  ] : [
1921
- renderTextField("Root path", modal.form.values.root, activeField === 0),
1922
- renderTextField("Skills path", modal.form.values.skills, activeField === 1),
1923
- renderTextField("Display name", modal.form.values.name, activeField === 2)
2041
+ renderTextField("Root path", modal.form.values.root, activeField === 0, theme),
2042
+ renderTextField("Skills path", modal.form.values.skills, activeField === 1, theme),
2043
+ renderTextField("Display name", modal.form.values.name, activeField === 2, theme)
1924
2044
  ];
1925
2045
  const platformFieldIndex = modal.kind === "add-agent" ? 4 : 3;
1926
2046
  const booleanFieldIndex = modal.kind === "add-agent" ? 5 : 4;
2047
+ const submitFieldIndex = 6;
1927
2048
  const platformLines = renderPlatformField(
1928
2049
  modal.form.values.platforms,
1929
2050
  platformIndex,
1930
- activeField === platformFieldIndex
2051
+ activeField === platformFieldIndex,
2052
+ theme
1931
2053
  );
1932
2054
  const booleanLabel = modal.kind === "add-agent" ? "Disabled by default" : "Enabled by default";
1933
2055
  const booleanValue = modal.kind === "add-agent" ? modal.form.values.disabledByDefault : modal.form.values.enabledByDefault;
1934
2056
  const secondaryBooleanLabel = modal.kind === "add-agent" ? null : "Disabled by default";
1935
2057
  return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", width, height, children: [
1936
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: title }),
1937
- modal.form.error === null ? null : /* @__PURE__ */ jsx7(Text7, { color: "red", children: modal.form.error }),
2058
+ /* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.fg.emphasis, children: title }),
2059
+ modal.form.error === null ? null : /* @__PURE__ */ jsx7(Text7, { color: theme.status.error, children: modal.form.error }),
1938
2060
  fields,
1939
- /* @__PURE__ */ jsx7(Text7, { bold: true, inverse: activeField === platformFieldIndex, children: "Platforms" }),
2061
+ /* @__PURE__ */ jsx7(Text7, { children: activeField === platformFieldIndex ? /* @__PURE__ */ jsx7(Text7, { backgroundColor: theme.bg.selection, children: /* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.fg.emphasis, children: "Platforms" }) }) : /* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.accent.primary, children: "Platforms" }) }),
1940
2062
  platformLines,
1941
2063
  renderBooleanField(
1942
2064
  booleanLabel,
1943
2065
  booleanValue,
1944
- activeField === booleanFieldIndex
2066
+ activeField === booleanFieldIndex,
2067
+ theme
1945
2068
  ),
1946
2069
  secondaryBooleanLabel === null ? null : renderBooleanField(
1947
2070
  secondaryBooleanLabel,
1948
2071
  modal.form.values.disabledByDefault,
1949
- activeField === booleanFieldIndex + 1
2072
+ activeField === booleanFieldIndex + 1,
2073
+ theme
1950
2074
  ),
1951
- /* @__PURE__ */ jsx7(Text7, { inverse: activeField === submitFieldIndex, children: "Submit" }),
2075
+ /* @__PURE__ */ jsx7(Text7, { children: activeField === submitFieldIndex ? /* @__PURE__ */ jsx7(Text7, { backgroundColor: theme.bg.selection, children: /* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.fg.emphasis, children: "Submit" }) }) : /* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.accent.primary, children: "Submit" }) }),
1952
2076
  modal.kind === "edit-agent" ? /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Leaving both defaults unchecked preserves the current setting." }) : null,
1953
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "[Up/Down] move [Enter] submit selected row [Esc] cancel" })
2077
+ /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "[Up/Down] move [Enter] submit [Esc] cancel" })
1954
2078
  ] });
1955
2079
  }
1956
2080
 
1957
2081
  // src/tui/components/SkillList.tsx
1958
2082
  import { Box as Box8, Text as Text8 } from "ink";
1959
2083
  import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1960
- function markerColor(skill) {
1961
- if (skill.kind === "enabled") {
1962
- return "green";
1963
- }
1964
- if (skill.kind === "issue") {
1965
- return skill.severity === "error" ? "red" : "yellow";
1966
- }
1967
- if (skill.kind === "unmanaged") {
1968
- return "yellow";
1969
- }
1970
- return "gray";
2084
+ function statusLabel2(skill) {
2085
+ if (skill.kind === "enabled") return "\u25CF";
2086
+ if (skill.kind === "disabled") return "\u25CB";
2087
+ if (skill.kind === "unmanaged") return "?";
2088
+ if (skill.severity === "error") return "!";
2089
+ return "*";
1971
2090
  }
1972
- function skillLabel(skill) {
1973
- if (skill.kind === "issue") {
1974
- return skill.issueCode;
1975
- }
1976
- return skill.name;
2091
+ function statusColor2(skill, theme) {
2092
+ if (skill.kind === "enabled") return theme.status.success;
2093
+ if (skill.kind === "disabled") return theme.fg.muted;
2094
+ if (skill.kind === "unmanaged") return theme.status.warning;
2095
+ return skill.severity === "error" ? theme.status.error : theme.status.warning;
2096
+ }
2097
+ function rowLabel(skill) {
2098
+ return skill.kind === "issue" ? skill.issueCode : skill.name;
1977
2099
  }
1978
2100
  function SkillList({
1979
2101
  agentId,
@@ -1985,40 +2107,111 @@ function SkillList({
1985
2107
  width = 28,
1986
2108
  height = 18
1987
2109
  }) {
2110
+ const theme = useTheme();
1988
2111
  const emptyMessage = loadingAgentName !== null ? `Loading skills for ${loadingAgentName}...` : agentId === null ? "Select an agent" : searchQuery !== void 0 && searchQuery.trim().length > 0 ? "No matching skills" : "No skills for this agent";
1989
2112
  return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width, height, children: [
1990
- /* @__PURE__ */ jsxs8(Text8, { bold: true, color: focused ? "cyan" : void 0, children: [
2113
+ /* @__PURE__ */ jsxs8(Text8, { bold: true, color: focused ? theme.fg.emphasis : theme.fg.muted, children: [
1991
2114
  "Skills for ",
1992
2115
  agentId ?? "none"
1993
2116
  ] }),
1994
2117
  skills.length === 0 ? /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: emptyMessage }) : skills.map((skill) => {
1995
2118
  const selected = skill.id === selectedSkillId;
1996
- return /* @__PURE__ */ jsxs8(Text8, { inverse: focused && selected, children: [
1997
- /* @__PURE__ */ jsx8(Text8, { color: markerColor(skill), children: skill.marker }),
1998
- /* @__PURE__ */ jsxs8(Text8, { children: [
1999
- " ",
2000
- skillLabel(skill)
2001
- ] })
2002
- ] }, skill.id);
2119
+ return /* @__PURE__ */ jsx8(Text8, { children: /* @__PURE__ */ jsxs8(
2120
+ Text8,
2121
+ {
2122
+ backgroundColor: focused && selected ? theme.bg.selection : void 0,
2123
+ children: [
2124
+ /* @__PURE__ */ jsx8(Text8, { bold: true, color: statusColor2(skill, theme), children: statusLabel2(skill) }),
2125
+ /* @__PURE__ */ jsxs8(
2126
+ Text8,
2127
+ {
2128
+ color: focused && selected ? theme.fg.emphasis : theme.fg.default,
2129
+ children: [
2130
+ " ",
2131
+ rowLabel(skill)
2132
+ ]
2133
+ }
2134
+ )
2135
+ ]
2136
+ }
2137
+ ) }, skill.id);
2003
2138
  })
2004
2139
  ] });
2005
2140
  }
2006
2141
 
2007
2142
  // src/tui/components/StatusLine.tsx
2008
2143
  import { Box as Box9, Text as Text9 } from "ink";
2009
- import { jsx as jsx9 } from "react/jsx-runtime";
2010
- function StatusLine({
2011
- busy,
2012
- statusMessage,
2013
- lastScanAt,
2014
- issueCount
2015
- }) {
2016
- const message = statusMessage ?? (busy ? "scanning..." : `Last scan: ${lastScanAt ?? "never"} | issues: ${issueCount}`);
2017
- return /* @__PURE__ */ jsx9(Box9, { height: 1, children: /* @__PURE__ */ jsx9(Text9, { color: busy ? "cyan" : void 0, children: message }) });
2144
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2145
+ function StatusLine({ busy, statusMessage, model }) {
2146
+ const theme = useTheme();
2147
+ if (busy) {
2148
+ return /* @__PURE__ */ jsxs9(Box9, { height: 1, children: [
2149
+ /* @__PURE__ */ jsx9(Text9, { bold: true, color: theme.status.info, children: "\u26A1 SkillMux" }),
2150
+ /* @__PURE__ */ jsx9(Text9, { color: theme.fg.muted, children: " \xB7 " }),
2151
+ /* @__PURE__ */ jsx9(Text9, { color: theme.status.info, children: statusMessage ?? "scanning..." })
2152
+ ] });
2153
+ }
2154
+ const agentCount = model.agents.length;
2155
+ let enabled = 0;
2156
+ let disabled = 0;
2157
+ let unmanaged = 0;
2158
+ let issueCount = 0;
2159
+ for (const agent of model.agents) {
2160
+ enabled += agent.enabledCount;
2161
+ disabled += agent.disabledCount;
2162
+ unmanaged += agent.unmanagedCount;
2163
+ issueCount += agent.issueCount;
2164
+ }
2165
+ if (statusMessage !== null) {
2166
+ return /* @__PURE__ */ jsxs9(Box9, { height: 1, children: [
2167
+ /* @__PURE__ */ jsx9(Text9, { bold: true, color: theme.fg.emphasis, children: "\u26A1 SkillMux" }),
2168
+ /* @__PURE__ */ jsx9(Text9, { color: theme.fg.muted, children: " \xB7 " }),
2169
+ /* @__PURE__ */ jsx9(Text9, { color: theme.status.warning, children: statusMessage })
2170
+ ] });
2171
+ }
2172
+ return /* @__PURE__ */ jsxs9(Box9, { height: 1, children: [
2173
+ /* @__PURE__ */ jsx9(Text9, { bold: true, color: theme.fg.emphasis, children: "\u26A1 SkillMux" }),
2174
+ /* @__PURE__ */ jsx9(Text9, { color: theme.fg.muted, children: " \xB7 " }),
2175
+ /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2176
+ agentCount,
2177
+ " agent",
2178
+ agentCount !== 1 ? "s" : ""
2179
+ ] }),
2180
+ /* @__PURE__ */ jsx9(Text9, { color: theme.fg.muted, children: " \u2502 " }),
2181
+ /* @__PURE__ */ jsxs9(Text9, { color: theme.status.success, children: [
2182
+ enabled,
2183
+ " enabled"
2184
+ ] }),
2185
+ /* @__PURE__ */ jsx9(Text9, { color: theme.fg.muted, children: " \u2502 " }),
2186
+ /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2187
+ disabled,
2188
+ " disabled"
2189
+ ] }),
2190
+ /* @__PURE__ */ jsx9(Text9, { color: theme.fg.muted, children: " \u2502 " }),
2191
+ /* @__PURE__ */ jsxs9(Text9, { color: theme.status.warning, children: [
2192
+ unmanaged,
2193
+ " unmanaged"
2194
+ ] }),
2195
+ issueCount > 0 ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
2196
+ /* @__PURE__ */ jsx9(Text9, { color: theme.fg.muted, children: " \u2502 " }),
2197
+ /* @__PURE__ */ jsxs9(Text9, { color: theme.status.error, children: [
2198
+ issueCount,
2199
+ " issue",
2200
+ issueCount !== 1 ? "s" : ""
2201
+ ] })
2202
+ ] }) : null,
2203
+ model.lastScanAt ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
2204
+ /* @__PURE__ */ jsx9(Text9, { color: theme.fg.muted, children: " \u2502 " }),
2205
+ /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2206
+ "Last scan: ",
2207
+ model.lastScanAt
2208
+ ] })
2209
+ ] }) : null
2210
+ ] });
2018
2211
  }
2019
2212
 
2020
2213
  // src/tui/components/Dashboard.tsx
2021
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2214
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
2022
2215
  var minimumWidth = 80;
2023
2216
  var minimumHeight = 24;
2024
2217
  var agentRatio = 0.26;
@@ -2029,6 +2222,18 @@ var skillMinimumWidth = 24;
2029
2222
  var detailMinimumWidth = 28;
2030
2223
  var largeModalWidth = 72;
2031
2224
  var largeModalHeight = 14;
2225
+ function horizontalBorder(left, mid, right, ...widths) {
2226
+ const h = "\u2500";
2227
+ let result = left;
2228
+ for (let i = 0; i < widths.length; i++) {
2229
+ result += h.repeat(widths[i]);
2230
+ if (i < widths.length - 1) {
2231
+ result += mid;
2232
+ }
2233
+ }
2234
+ result += right;
2235
+ return result;
2236
+ }
2032
2237
  function paneWidths(width) {
2033
2238
  const agentWidth = Math.max(agentMinimumWidth, Math.round(width * agentRatio));
2034
2239
  const skillWidth = Math.max(skillMinimumWidth, Math.round(width * skillRatio));
@@ -2052,6 +2257,7 @@ function Dashboard({
2052
2257
  height,
2053
2258
  modalInteraction
2054
2259
  }) {
2260
+ const theme = useTheme();
2055
2261
  const interaction = modalInteraction ?? {
2056
2262
  fieldIndex: 0,
2057
2263
  platformIndex: 0,
@@ -2085,16 +2291,19 @@ function Dashboard({
2085
2291
  const { agentWidth, skillWidth, detailWidth } = paneWidths(width);
2086
2292
  const modalWidth = Math.min(width - 4, largeModalWidth);
2087
2293
  const modalHeight = Math.min(bodyHeight, largeModalHeight);
2088
- return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column", width, height, children: [
2089
- /* @__PURE__ */ jsx10(
2294
+ const adjustedDetailWidth = Math.max(0, detailWidth - 2);
2295
+ const contentHeight = Math.max(0, bodyHeight - 2);
2296
+ const separatorBorder1 = state.focus === "agents" ? theme.border.focused : theme.border.default;
2297
+ const separatorBorder2 = state.focus === "skills" ? theme.border.focused : theme.border.default;
2298
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", width, height, children: [
2299
+ /* @__PURE__ */ jsx10(Box10, { height: 1, children: /* @__PURE__ */ jsx10(
2090
2300
  StatusLine,
2091
2301
  {
2092
2302
  busy: state.busy,
2093
2303
  statusMessage: state.statusMessage,
2094
- lastScanAt: state.model.lastScanAt,
2095
- issueCount: state.model.issueCount
2304
+ model: state.model
2096
2305
  }
2097
- ),
2306
+ ) }),
2098
2307
  largeModal ? /* @__PURE__ */ jsx10(
2099
2308
  Box10,
2100
2309
  {
@@ -2122,42 +2331,47 @@ function Dashboard({
2122
2331
  }
2123
2332
  ) : state.modal?.kind === "confirm-remove-agent" ? /* @__PURE__ */ jsx10(ConfirmDialog, { modal: state.modal }) : null })
2124
2333
  }
2125
- ) : /* @__PURE__ */ jsxs9(Box10, { flexDirection: "row", width, height: bodyHeight, children: [
2126
- /* @__PURE__ */ jsx10(
2127
- AgentList,
2128
- {
2129
- agents: visibleAgents,
2130
- selectedAgentId: state.model.selectedAgentId,
2131
- focused: state.focus === "agents",
2132
- searchQuery: state.search?.panel === "agents" ? state.search.query : void 0,
2133
- width: agentWidth,
2134
- height: bodyHeight
2135
- }
2136
- ),
2137
- /* @__PURE__ */ jsx10(
2138
- SkillList,
2139
- {
2140
- agentId: state.model.selectedAgentId,
2141
- skills: visibleSkills,
2142
- selectedSkillId: state.model.selectedSkillId,
2143
- focused: state.focus === "skills",
2144
- searchQuery: state.search?.panel === "skills" ? state.search.query : void 0,
2145
- loadingAgentName: loadingAgent?.name ?? null,
2146
- width: skillWidth,
2147
- height: bodyHeight
2148
- }
2149
- ),
2150
- /* @__PURE__ */ jsx10(
2151
- DetailPane,
2152
- {
2153
- selectedAgent,
2154
- selectedSkill,
2155
- focused: state.focus === "detail",
2156
- loadingAgentName: loadingAgent?.name ?? null,
2157
- width: detailWidth,
2158
- height: bodyHeight
2159
- }
2160
- )
2334
+ ) : /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
2335
+ /* @__PURE__ */ jsx10(Text10, { color: theme.border.default, children: horizontalBorder("\u251C", "\u252C", "\u2524", agentWidth, skillWidth, detailWidth) }),
2336
+ /* @__PURE__ */ jsxs10(Box10, { flexDirection: "row", width, height: contentHeight, children: [
2337
+ /* @__PURE__ */ jsx10(
2338
+ AgentList,
2339
+ {
2340
+ agents: visibleAgents,
2341
+ selectedAgentId: state.model.selectedAgentId,
2342
+ focused: state.focus === "agents",
2343
+ searchQuery: state.search?.panel === "agents" ? state.search.query : void 0,
2344
+ width: agentWidth,
2345
+ height: contentHeight
2346
+ }
2347
+ ),
2348
+ /* @__PURE__ */ jsx10(Text10, { color: separatorBorder1, children: "\u2502" }),
2349
+ /* @__PURE__ */ jsx10(
2350
+ SkillList,
2351
+ {
2352
+ agentId: state.model.selectedAgentId,
2353
+ skills: visibleSkills,
2354
+ selectedSkillId: state.model.selectedSkillId,
2355
+ focused: state.focus === "skills",
2356
+ searchQuery: state.search?.panel === "skills" ? state.search.query : void 0,
2357
+ loadingAgentName: loadingAgent?.name ?? null,
2358
+ width: skillWidth,
2359
+ height: contentHeight
2360
+ }
2361
+ ),
2362
+ /* @__PURE__ */ jsx10(Text10, { color: separatorBorder2, children: "\u2502" }),
2363
+ /* @__PURE__ */ jsx10(
2364
+ DetailPane,
2365
+ {
2366
+ selectedAgent,
2367
+ selectedSkill,
2368
+ focused: state.focus === "detail",
2369
+ loadingAgentName: loadingAgent?.name ?? null,
2370
+ width: adjustedDetailWidth,
2371
+ height: contentHeight
2372
+ }
2373
+ )
2374
+ ] })
2161
2375
  ] }),
2162
2376
  state.modal?.kind === "help" ? /* @__PURE__ */ jsx10(HelpOverlay, {}) : null,
2163
2377
  state.modal?.kind === "confirm-adopt" || state.modal?.kind === "confirm-adopt-all" || state.modal?.kind === "confirm-remove" || state.modal?.kind === "confirm-discard-dirty-form" ? /* @__PURE__ */ jsx10(ConfirmDialog, { modal: state.modal }) : null,
@@ -3099,13 +3313,14 @@ function App({
3099
3313
  setState(updateTuiState(state, { type: "request-scan" }));
3100
3314
  }
3101
3315
  });
3316
+ const theme = useMemo(() => resolveTheme(), []);
3102
3317
  if (loadError !== null) {
3103
3318
  return /* @__PURE__ */ jsx11(Text11, { color: "red", children: loadError });
3104
3319
  }
3105
3320
  if (state === null) {
3106
3321
  return /* @__PURE__ */ jsx11(Text11, { children: "loading dashboard..." });
3107
3322
  }
3108
- return sizeBridgeEnabled ? /* @__PURE__ */ jsx11(
3323
+ return /* @__PURE__ */ jsx11(ThemeProvider, { value: theme, children: sizeBridgeEnabled ? /* @__PURE__ */ jsx11(
3109
3324
  BridgedDashboardViewport,
3110
3325
  {
3111
3326
  state,
@@ -3122,7 +3337,7 @@ function App({
3122
3337
  terminalHeight,
3123
3338
  modalInteraction
3124
3339
  }
3125
- );
3340
+ ) });
3126
3341
  }
3127
3342
 
3128
3343
  // src/tui/launch-tui.tsx
@@ -3185,4 +3400,4 @@ function sleep(ms) {
3185
3400
  export {
3186
3401
  launchTui
3187
3402
  };
3188
- //# sourceMappingURL=launch-tui-IC7COEGE.js.map
3403
+ //# sourceMappingURL=launch-tui-JD4F62FS.js.map