@inf-monkeys-tech/monkeys-design 1.0.77 → 1.0.78

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.
@@ -1517,13 +1517,74 @@ var AgentWorkbenchSidebarContainer = React5.forwardRef(
1517
1517
  }
1518
1518
  );
1519
1519
  AgentWorkbenchSidebarContainer.displayName = "AgentWorkbenchSidebarContainer";
1520
- function ItemAvatar({ item }) {
1521
- const [failed, setFailed] = React5.useState(false);
1522
- if (item.iconUrl && !failed) {
1523
- return /* @__PURE__ */ jsxRuntime.jsx("img", { src: item.iconUrl, alt: "", className: "size-full object-cover", onError: () => setFailed(true) });
1524
- }
1525
- const initial = item.name.trim().charAt(0).toLocaleUpperCase();
1526
- return initial ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: initial }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bot, { className: "size-4" });
1520
+ function AgentWorkbenchSidebarSearch({
1521
+ value,
1522
+ label,
1523
+ placeholder = label,
1524
+ className,
1525
+ onChange
1526
+ }) {
1527
+ const messages = useMonkeysLocaleMessages().agentWorkbench.navigation;
1528
+ const searchRef = React5.useRef(null);
1529
+ React5.useEffect(() => {
1530
+ const handleShortcut = (event) => {
1531
+ if (!(event.ctrlKey || event.metaKey) || event.key.toLocaleLowerCase() !== "k")
1532
+ return;
1533
+ event.preventDefault();
1534
+ searchRef.current?.focus();
1535
+ searchRef.current?.select();
1536
+ };
1537
+ window.addEventListener("keydown", handleShortcut);
1538
+ return () => window.removeEventListener("keydown", handleShortcut);
1539
+ }, []);
1540
+ return /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { className: cn2("h-10 rounded-lg bg-card", className), children: [
1541
+ /* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "size-4", "aria-hidden": "true" }) }),
1542
+ /* @__PURE__ */ jsxRuntime.jsx(
1543
+ InputGroupInput,
1544
+ {
1545
+ ref: searchRef,
1546
+ type: "search",
1547
+ value,
1548
+ "aria-label": label,
1549
+ placeholder,
1550
+ className: "min-w-0 [&::-webkit-search-cancel-button]:hidden",
1551
+ onChange: (event) => onChange(event.target.value),
1552
+ onKeyDown: (event) => {
1553
+ if (event.key !== "Escape") return;
1554
+ onChange("");
1555
+ event.currentTarget.blur();
1556
+ }
1557
+ }
1558
+ ),
1559
+ value ? /* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxRuntime.jsx(
1560
+ InputGroupButton,
1561
+ {
1562
+ size: "icon-xs",
1563
+ "aria-label": messages.clearSearch,
1564
+ onClick: () => onChange(""),
1565
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3.5", "aria-hidden": "true" })
1566
+ }
1567
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "border border-border px-1.5 py-0.5 text-[10px]", children: "Ctrl K" }) })
1568
+ ] });
1569
+ }
1570
+ function AgentWorkbenchSidebarNewSessionButton({
1571
+ label,
1572
+ className,
1573
+ onClick
1574
+ }) {
1575
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1576
+ Button,
1577
+ {
1578
+ type: "button",
1579
+ variant: "ghost",
1580
+ className: cn2("h-9 w-full justify-start gap-2 px-3 text-sm", className),
1581
+ onClick,
1582
+ children: [
1583
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SquarePen, { className: "size-4", "aria-hidden": "true" }),
1584
+ label
1585
+ ]
1586
+ }
1587
+ );
1527
1588
  }
1528
1589
  function SessionAvatar({ item }) {
1529
1590
  const [failed, setFailed] = React5.useState(false);
@@ -1541,13 +1602,329 @@ function SessionAvatar({ item }) {
1541
1602
  }
1542
1603
  return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { className: "size-5", "aria-hidden": "true" });
1543
1604
  }
1544
- function SessionMeta({ item, locale }) {
1605
+ function SessionMeta({ item }) {
1606
+ const { locale } = useMonkeysLocale();
1545
1607
  const messages = useMonkeysLocaleMessages().agentWorkbench.navigation;
1546
1608
  return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
1547
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-xs text-foreground/80", children: new Intl.DateTimeFormat(locale, { dateStyle: "medium", timeStyle: "short" }).format(new Date(item.updatedAt)) }),
1548
- item.mode ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn2("shrink-0 rounded-full px-1.5 py-0.5 text-[10px] font-medium leading-none", item.mode === "work" ? "bg-primary/10 text-primary" : "bg-muted text-foreground"), children: item.mode === "work" ? messages.work : messages.chat }) : null
1609
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-xs text-foreground/80", children: new Intl.DateTimeFormat(locale, {
1610
+ dateStyle: "medium",
1611
+ timeStyle: "short"
1612
+ }).format(new Date(item.updatedAt)) }),
1613
+ item.mode ? /* @__PURE__ */ jsxRuntime.jsx(
1614
+ "span",
1615
+ {
1616
+ className: cn2(
1617
+ "shrink-0 rounded-full px-1.5 py-0.5 text-[10px] font-medium leading-none",
1618
+ item.mode === "work" ? "bg-primary/10 text-primary" : "bg-muted text-foreground"
1619
+ ),
1620
+ children: item.mode === "work" ? messages.work : messages.chat
1621
+ }
1622
+ ) : null
1549
1623
  ] });
1550
1624
  }
1625
+ function StatusIndicator({
1626
+ status
1627
+ }) {
1628
+ const messages = useMonkeysLocaleMessages().agentWorkbench.navigation;
1629
+ if (status === "running") {
1630
+ return /* @__PURE__ */ jsxRuntime.jsx(
1631
+ lucideReact.Loader2,
1632
+ {
1633
+ className: "size-4 animate-spin text-primary",
1634
+ "aria-label": messages.running
1635
+ }
1636
+ );
1637
+ }
1638
+ if (status === "completed") {
1639
+ return /* @__PURE__ */ jsxRuntime.jsx(
1640
+ lucideReact.CheckCircle2,
1641
+ {
1642
+ className: "size-4 text-primary",
1643
+ "aria-label": messages.completed
1644
+ }
1645
+ );
1646
+ }
1647
+ if (status === "error") {
1648
+ return /* @__PURE__ */ jsxRuntime.jsx(
1649
+ lucideReact.AlertCircle,
1650
+ {
1651
+ className: "size-4 text-destructive-text",
1652
+ "aria-label": messages.failed
1653
+ }
1654
+ );
1655
+ }
1656
+ return null;
1657
+ }
1658
+ function AgentWorkbenchSessionList({
1659
+ sessions,
1660
+ selectedSessionId,
1661
+ status = "ready",
1662
+ error,
1663
+ query = "",
1664
+ emptyLabel,
1665
+ noResultsLabel,
1666
+ retryLabel,
1667
+ groupByMode = false,
1668
+ showHeading = false,
1669
+ className,
1670
+ itemClassName,
1671
+ capabilities,
1672
+ onSelect,
1673
+ onTogglePin,
1674
+ onRename,
1675
+ onDelete,
1676
+ onRetry
1677
+ }) {
1678
+ const messages = useMonkeysLocaleMessages().agentWorkbench.navigation;
1679
+ const renameInputRef = React5.useRef(null);
1680
+ const [editingSessionId, setEditingSessionId] = React5.useState();
1681
+ const [editingTitle, setEditingTitle] = React5.useState("");
1682
+ React5.useEffect(() => {
1683
+ if (!editingSessionId) return;
1684
+ renameInputRef.current?.focus();
1685
+ renameInputRef.current?.select();
1686
+ }, [editingSessionId]);
1687
+ const cancelRename = () => {
1688
+ setEditingSessionId(void 0);
1689
+ setEditingTitle("");
1690
+ };
1691
+ const saveRename = (item) => {
1692
+ const title = editingTitle.trim();
1693
+ if (title && title !== item.title) onRename?.(item.id, title);
1694
+ cancelRename();
1695
+ };
1696
+ if (status === "loading" && sessions.length === 0) {
1697
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-8 text-center text-sm text-muted-foreground", children: messages.loading });
1698
+ }
1699
+ if (status === "error") {
1700
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-3 px-3 py-8 text-center", children: [
1701
+ /* @__PURE__ */ jsxRuntime.jsx(
1702
+ "p",
1703
+ {
1704
+ className: "max-w-full break-words text-sm text-muted-foreground",
1705
+ role: "alert",
1706
+ children: error
1707
+ }
1708
+ ),
1709
+ onRetry ? /* @__PURE__ */ jsxRuntime.jsxs(
1710
+ Button,
1711
+ {
1712
+ type: "button",
1713
+ variant: "ghost",
1714
+ size: "sm",
1715
+ className: "gap-1.5 px-0 text-sm text-primary hover:text-primary",
1716
+ onClick: onRetry,
1717
+ children: [
1718
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "size-3.5", "aria-hidden": "true" }),
1719
+ retryLabel ?? messages.retry
1720
+ ]
1721
+ }
1722
+ ) : null
1723
+ ] });
1724
+ }
1725
+ if (sessions.length === 0) {
1726
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-8 text-center text-sm text-muted-foreground", children: query ? noResultsLabel : emptyLabel });
1727
+ }
1728
+ const renderItems = (items) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: items.map((item) => {
1729
+ const percent = item.contextUsage && item.contextUsage.maxTokens > 0 ? Math.min(
1730
+ 100,
1731
+ Math.round(
1732
+ item.contextUsage.usedTokens / item.contextUsage.maxTokens * 100
1733
+ )
1734
+ ) : void 0;
1735
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1736
+ "div",
1737
+ {
1738
+ "aria-current": item.id === selectedSessionId ? "page" : void 0,
1739
+ className: cn2(
1740
+ "group flex w-full min-w-0 items-center gap-3 rounded-lg border border-transparent px-3 py-2 text-left hover:bg-muted aria-[current=page]:border-primary aria-[current=page]:bg-muted",
1741
+ itemClassName
1742
+ ),
1743
+ children: [
1744
+ editingSessionId === item.id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
1745
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(SessionAvatar, { item }) }),
1746
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
1747
+ /* @__PURE__ */ jsxRuntime.jsx(
1748
+ Input,
1749
+ {
1750
+ ref: renameInputRef,
1751
+ value: editingTitle,
1752
+ "aria-label": messages.rename,
1753
+ appearance: "compact",
1754
+ className: "h-6 w-full border-primary px-1.5 text-sm font-medium",
1755
+ onChange: (event) => setEditingTitle(event.target.value),
1756
+ onClick: (event) => event.stopPropagation(),
1757
+ onBlur: () => saveRename(item),
1758
+ onKeyDown: (event) => {
1759
+ event.stopPropagation();
1760
+ if (event.key === "Enter") {
1761
+ event.preventDefault();
1762
+ saveRename(item);
1763
+ } else if (event.key === "Escape") {
1764
+ event.preventDefault();
1765
+ cancelRename();
1766
+ }
1767
+ }
1768
+ }
1769
+ ),
1770
+ /* @__PURE__ */ jsxRuntime.jsx(SessionMeta, { item })
1771
+ ] })
1772
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(
1773
+ "button",
1774
+ {
1775
+ type: "button",
1776
+ title: item.title,
1777
+ className: "flex min-w-0 flex-1 items-center gap-3 text-left",
1778
+ onClick: () => onSelect(item.id),
1779
+ children: [
1780
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(SessionAvatar, { item }) }),
1781
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
1782
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-sm font-medium", children: item.title }),
1783
+ /* @__PURE__ */ jsxRuntime.jsx(SessionMeta, { item })
1784
+ ] })
1785
+ ]
1786
+ }
1787
+ ),
1788
+ /* @__PURE__ */ jsxRuntime.jsxs(
1789
+ "span",
1790
+ {
1791
+ "data-agent-workbench-item-actions": true,
1792
+ className: "flex shrink-0 items-center gap-1",
1793
+ children: [
1794
+ percent !== void 0 && item.status === "idle" ? /* @__PURE__ */ jsxRuntime.jsxs(
1795
+ "span",
1796
+ {
1797
+ className: "text-xs text-foreground",
1798
+ "aria-label": messages.contextUsage({ percent }),
1799
+ children: [
1800
+ percent,
1801
+ "%"
1802
+ ]
1803
+ }
1804
+ ) : /* @__PURE__ */ jsxRuntime.jsx(StatusIndicator, { status: item.status }),
1805
+ capabilities?.pin ? /* @__PURE__ */ jsxRuntime.jsx(
1806
+ Button,
1807
+ {
1808
+ type: "button",
1809
+ variant: "ghost",
1810
+ size: "icon",
1811
+ "aria-label": item.pinned ? messages.unpin : messages.pin,
1812
+ className: cn2(
1813
+ "size-8 text-muted-foreground opacity-0 group-hover:opacity-100",
1814
+ item.pinned && "text-primary opacity-100"
1815
+ ),
1816
+ onClick: (event) => {
1817
+ event.stopPropagation();
1818
+ onTogglePin?.(item.id, !item.pinned);
1819
+ },
1820
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1821
+ lucideReact.Pin,
1822
+ {
1823
+ className: cn2("size-4", item.pinned && "fill-current")
1824
+ }
1825
+ )
1826
+ }
1827
+ ) : null,
1828
+ capabilities?.rename || capabilities?.delete ? /* @__PURE__ */ jsxRuntime.jsx(
1829
+ "span",
1830
+ {
1831
+ onClick: (event) => event.stopPropagation(),
1832
+ onKeyDown: (event) => event.stopPropagation(),
1833
+ children: /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu2, { children: [
1834
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
1835
+ Button,
1836
+ {
1837
+ type: "button",
1838
+ variant: "ghost",
1839
+ size: "icon",
1840
+ className: "size-8",
1841
+ "aria-label": messages.actions,
1842
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ellipsis, { className: "size-4", "aria-hidden": "true" })
1843
+ }
1844
+ ) }),
1845
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "end", children: [
1846
+ capabilities.rename ? /* @__PURE__ */ jsxRuntime.jsxs(
1847
+ DropdownMenuItem,
1848
+ {
1849
+ onSelect: () => {
1850
+ setEditingSessionId(item.id);
1851
+ setEditingTitle(item.title);
1852
+ },
1853
+ children: [
1854
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "mr-2 size-4", "aria-hidden": "true" }),
1855
+ messages.rename
1856
+ ]
1857
+ }
1858
+ ) : null,
1859
+ capabilities.delete ? /* @__PURE__ */ jsxRuntime.jsxs(
1860
+ DropdownMenuItem,
1861
+ {
1862
+ className: "text-destructive-text",
1863
+ onSelect: () => onDelete?.(item.id),
1864
+ children: [
1865
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "mr-2 size-4", "aria-hidden": "true" }),
1866
+ messages.delete
1867
+ ]
1868
+ }
1869
+ ) : null
1870
+ ] })
1871
+ ] })
1872
+ }
1873
+ ) : null
1874
+ ]
1875
+ }
1876
+ )
1877
+ ]
1878
+ },
1879
+ item.id
1880
+ );
1881
+ }) });
1882
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn2("space-y-2", className), children: [
1883
+ showHeading && !groupByMode ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 px-3 text-xs font-medium text-muted-foreground", children: messages.recentSessions }) : null,
1884
+ groupByMode ? [
1885
+ {
1886
+ id: "chatbot",
1887
+ label: messages.chats,
1888
+ icon: lucideReact.MessageSquare,
1889
+ items: sessions.filter((item) => item.mode !== "work")
1890
+ },
1891
+ {
1892
+ id: "agent",
1893
+ label: messages.agents,
1894
+ icon: lucideReact.Bot,
1895
+ items: sessions.filter((item) => item.mode === "work")
1896
+ }
1897
+ ].map(({ id, label, icon: Icon2, items }) => /* @__PURE__ */ jsxRuntime.jsxs("details", { open: true, "aria-label": label, children: [
1898
+ /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex h-9 cursor-pointer list-none items-center gap-2 rounded-md px-3 text-sm font-semibold hover:bg-muted", children: [
1899
+ /* @__PURE__ */ jsxRuntime.jsx(
1900
+ Icon2,
1901
+ {
1902
+ className: "size-4 shrink-0 text-muted-foreground",
1903
+ "aria-hidden": "true"
1904
+ }
1905
+ ),
1906
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: label })
1907
+ ] }),
1908
+ renderItems(items)
1909
+ ] }, id)) : renderItems(sessions)
1910
+ ] });
1911
+ }
1912
+ function ItemAvatar({ item }) {
1913
+ const [failed, setFailed] = React5.useState(false);
1914
+ if (item.iconUrl && !failed) {
1915
+ return /* @__PURE__ */ jsxRuntime.jsx(
1916
+ "img",
1917
+ {
1918
+ src: item.iconUrl,
1919
+ alt: "",
1920
+ className: "size-full object-cover",
1921
+ onError: () => setFailed(true)
1922
+ }
1923
+ );
1924
+ }
1925
+ const initial = item.name.trim().charAt(0).toLocaleUpperCase();
1926
+ return initial ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: initial }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bot, { className: "size-4" });
1927
+ }
1551
1928
  function CollectionState({
1552
1929
  status,
1553
1930
  empty,
@@ -1563,11 +1940,28 @@ function CollectionState({
1563
1940
  }
1564
1941
  if (status === "error") {
1565
1942
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-3 px-3 py-8 text-center", children: [
1566
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-full break-words text-sm text-muted-foreground", role: "alert", children: error }),
1567
- /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", className: "gap-1.5 px-0 text-sm text-primary hover:text-primary", onClick: onRetry, children: [
1568
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "size-3.5", "aria-hidden": "true" }),
1569
- messages.retry
1570
- ] })
1943
+ /* @__PURE__ */ jsxRuntime.jsx(
1944
+ "p",
1945
+ {
1946
+ className: "max-w-full break-words text-sm text-muted-foreground",
1947
+ role: "alert",
1948
+ children: error
1949
+ }
1950
+ ),
1951
+ /* @__PURE__ */ jsxRuntime.jsxs(
1952
+ Button,
1953
+ {
1954
+ type: "button",
1955
+ variant: "ghost",
1956
+ size: "sm",
1957
+ className: "gap-1.5 px-0 text-sm text-primary hover:text-primary",
1958
+ onClick: onRetry,
1959
+ children: [
1960
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "size-3.5", "aria-hidden": "true" }),
1961
+ messages.retry
1962
+ ]
1963
+ }
1964
+ )
1571
1965
  ] });
1572
1966
  }
1573
1967
  if (!hasItems) {
@@ -1575,40 +1969,6 @@ function CollectionState({
1575
1969
  }
1576
1970
  return null;
1577
1971
  }
1578
- function StatusIndicator({ status }) {
1579
- const messages = useMonkeysLocaleMessages().agentWorkbench.navigation;
1580
- if (status === "running") {
1581
- return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-4 animate-spin text-primary", "aria-label": messages.running });
1582
- }
1583
- if (status === "completed") {
1584
- return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "size-4 text-primary", "aria-label": messages.completed });
1585
- }
1586
- if (status === "error") {
1587
- return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "size-4 text-destructive-text", "aria-label": messages.failed });
1588
- }
1589
- return null;
1590
- }
1591
- function SessionActions({
1592
- item,
1593
- capabilities,
1594
- onIntent
1595
- }) {
1596
- const messages = useMonkeysLocaleMessages().agentWorkbench.navigation;
1597
- if (!capabilities.renameSessions && !capabilities.deleteSessions) return null;
1598
- return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu2, { children: [
1599
- /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "size-8", "aria-label": messages.actions, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ellipsis, { className: "size-4", "aria-hidden": "true" }) }) }),
1600
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "end", children: [
1601
- capabilities.renameSessions ? /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onSelect: () => onIntent?.({ type: "rename-session", sessionId: item.id, title: item.title }), children: [
1602
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "mr-2 size-4", "aria-hidden": "true" }),
1603
- messages.rename
1604
- ] }) : null,
1605
- capabilities.deleteSessions ? /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { className: "text-destructive-text", onSelect: () => onIntent?.({ type: "delete-session", sessionId: item.id }), children: [
1606
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "mr-2 size-4", "aria-hidden": "true" }),
1607
- messages.delete
1608
- ] }) : null
1609
- ] })
1610
- ] });
1611
- }
1612
1972
  function AgentWorkbenchSidebar({
1613
1973
  viewModel,
1614
1974
  navigationMode,
@@ -1620,115 +1980,38 @@ function AgentWorkbenchSidebar({
1620
1980
  classNames,
1621
1981
  onIntent
1622
1982
  }) {
1623
- const { locale } = useMonkeysLocale();
1624
1983
  const messages = useMonkeysLocaleMessages().agentWorkbench.navigation;
1625
- const resolvedConfig = React5.useMemo(() => monkeys.resolveAgentWorkbenchSidebarConfig(config), [config]);
1626
- const visibleSections = React5.useMemo(() => new Set(resolvedConfig.visibleSections), [resolvedConfig.visibleSections]);
1984
+ const resolvedConfig = React5.useMemo(
1985
+ () => monkeys.resolveAgentWorkbenchSidebarConfig(config),
1986
+ [config]
1987
+ );
1988
+ const visibleSections = React5.useMemo(
1989
+ () => new Set(resolvedConfig.visibleSections),
1990
+ [resolvedConfig.visibleSections]
1991
+ );
1627
1992
  const sessionsOnly = navigationMode === "sessions-only" || navigationMode === void 0 && resolvedConfig.navigationMode !== "default";
1628
1993
  const showAgents = visibleSections.has("agents") && !sessionsOnly;
1629
1994
  const showSessions = visibleSections.has("sessions");
1630
- const searchRef = React5.useRef(null);
1631
- const renameInputRef = React5.useRef(null);
1632
- const [editingSessionId, setEditingSessionId] = React5.useState();
1633
- const [editingTitle, setEditingTitle] = React5.useState("");
1634
1995
  const query = viewModel.searchQuery.trim().toLocaleLowerCase();
1635
1996
  const agents = React5.useMemo(
1636
- () => viewModel.agents.items.filter((item) => !query || `${item.name} ${item.description ?? ""}`.toLocaleLowerCase().includes(query)),
1997
+ () => viewModel.agents.items.filter(
1998
+ (item) => !query || `${item.name} ${item.description ?? ""}`.toLocaleLowerCase().includes(query)
1999
+ ),
1637
2000
  [query, viewModel.agents.items]
1638
2001
  );
1639
2002
  const sessions = React5.useMemo(
1640
- () => viewModel.sessions.items.filter((item) => !query || item.title.toLocaleLowerCase().includes(query)),
2003
+ () => viewModel.sessions.items.filter(
2004
+ (item) => !query || item.title.toLocaleLowerCase().includes(query)
2005
+ ),
1641
2006
  [query, viewModel.sessions.items]
1642
2007
  );
1643
- const chatbotSessions = React5.useMemo(() => sessions.filter((item) => item.mode !== "work"), [sessions]);
1644
- const agentSessions = React5.useMemo(() => sessions.filter((item) => item.mode === "work"), [sessions]);
1645
- React5.useEffect(() => {
1646
- const handleShortcut = (event) => {
1647
- if (!(event.ctrlKey || event.metaKey) || event.key.toLocaleLowerCase() !== "k") return;
1648
- event.preventDefault();
1649
- searchRef.current?.focus();
1650
- searchRef.current?.select();
1651
- };
1652
- window.addEventListener("keydown", handleShortcut);
1653
- return () => window.removeEventListener("keydown", handleShortcut);
1654
- }, []);
1655
- React5.useEffect(() => {
1656
- if (!editingSessionId) return;
1657
- renameInputRef.current?.focus();
1658
- renameInputRef.current?.select();
1659
- }, [editingSessionId]);
1660
- const beginRenameSession = (item) => {
1661
- setEditingSessionId(item.id);
1662
- setEditingTitle(item.title);
1663
- };
1664
- const cancelRenameSession = () => {
1665
- setEditingSessionId(void 0);
1666
- setEditingTitle("");
1667
- };
1668
- const saveRenameSession = (item) => {
1669
- const title = editingTitle.trim();
1670
- if (title && title !== item.title) {
1671
- onIntent?.({ type: "rename-session", sessionId: item.id, title });
1672
- }
1673
- cancelRenameSession();
1674
- };
1675
- const renderSessionItems = (items) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: items.map((item) => {
1676
- const percent = item.contextUsage && item.contextUsage.maxTokens > 0 ? Math.min(100, Math.round(item.contextUsage.usedTokens / item.contextUsage.maxTokens * 100)) : void 0;
1677
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { "aria-current": item.id === viewModel.selectedSessionItem ? "page" : void 0, className: cn2("group flex w-full min-w-0 items-center gap-3 rounded-lg border border-transparent px-3 py-2 text-left hover:bg-muted aria-[current=page]:border-primary aria-[current=page]:bg-muted", classNames?.item), children: [
1678
- editingSessionId === item.id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
1679
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(SessionAvatar, { item }) }),
1680
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
1681
- /* @__PURE__ */ jsxRuntime.jsx(
1682
- Input,
1683
- {
1684
- ref: renameInputRef,
1685
- value: editingTitle,
1686
- "aria-label": messages.rename,
1687
- appearance: "compact",
1688
- className: "h-6 w-full border-primary px-1.5 text-sm font-medium",
1689
- onChange: (event) => setEditingTitle(event.target.value),
1690
- onClick: (event) => event.stopPropagation(),
1691
- onBlur: () => saveRenameSession(item),
1692
- onKeyDown: (event) => {
1693
- event.stopPropagation();
1694
- if (event.key === "Enter") {
1695
- event.preventDefault();
1696
- saveRenameSession(item);
1697
- } else if (event.key === "Escape") {
1698
- event.preventDefault();
1699
- cancelRenameSession();
1700
- }
1701
- }
1702
- }
1703
- ),
1704
- /* @__PURE__ */ jsxRuntime.jsx(SessionMeta, { item, locale })
1705
- ] })
1706
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", title: item.title, className: "flex min-w-0 flex-1 items-center gap-3 text-left", onClick: () => onIntent?.({ type: "select-session", sessionId: item.id }), children: [
1707
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(SessionAvatar, { item }) }),
1708
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
1709
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-sm font-medium", children: item.title }),
1710
- /* @__PURE__ */ jsxRuntime.jsx(SessionMeta, { item, locale })
1711
- ] })
1712
- ] }),
1713
- /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-agent-workbench-item-actions": true, className: "flex shrink-0 items-center gap-1", children: [
1714
- percent !== void 0 && item.status === "idle" ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-foreground", "aria-label": messages.contextUsage({ percent }), children: [
1715
- percent,
1716
- "%"
1717
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(StatusIndicator, { status: item.status }),
1718
- viewModel.capabilities.pinSessions ? /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": item.pinned ? messages.unpin : messages.pin, className: cn2("size-8 text-muted-foreground opacity-0 group-hover:opacity-100", item.pinned && "text-primary opacity-100"), onClick: (event) => {
1719
- event.stopPropagation();
1720
- onIntent?.({ type: "toggle-session-pin", sessionId: item.id, pinned: !item.pinned });
1721
- }, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pin, { className: cn2("size-4", item.pinned && "fill-current") }) }) : null,
1722
- /* @__PURE__ */ jsxRuntime.jsx("span", { onClick: (event) => event.stopPropagation(), onKeyDown: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsx(SessionActions, { item, capabilities: viewModel.capabilities, onIntent: (intent) => intent.type === "rename-session" ? beginRenameSession(item) : onIntent?.(intent) }) })
1723
- ] })
1724
- ] }, item.id);
1725
- }) });
1726
2008
  return /* @__PURE__ */ jsxRuntime.jsx(
1727
2009
  Tabs,
1728
2010
  {
1729
2011
  value: sessionsOnly || !showAgents ? "sessions" : viewModel.activeTab,
1730
2012
  onValueChange: (value) => {
1731
- if (!sessionsOnly && (value === "agents" || value === "sessions")) onIntent?.({ type: "change-tab", tab: value });
2013
+ if (!sessionsOnly && (value === "agents" || value === "sessions"))
2014
+ onIntent?.({ type: "change-tab", tab: value });
1732
2015
  },
1733
2016
  className: "h-full min-h-0",
1734
2017
  children: /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1737,115 +2020,230 @@ function AgentWorkbenchSidebar({
1737
2020
  "data-sidebar-width-percent": resolvedConfig.widthPercent,
1738
2021
  "aria-label": messages.tabsLabel,
1739
2022
  header: visibleSections.has("header") ? header : void 0,
1740
- search: visibleSections.has("search") ? /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { className: cn2("h-10 rounded-lg bg-card", classNames?.search), children: [
1741
- /* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "size-4", "aria-hidden": "true" }) }),
1742
- /* @__PURE__ */ jsxRuntime.jsx(
1743
- InputGroupInput,
2023
+ search: visibleSections.has("search") ? /* @__PURE__ */ jsxRuntime.jsx(
2024
+ AgentWorkbenchSidebarSearch,
2025
+ {
2026
+ value: viewModel.searchQuery,
2027
+ label: sessionsOnly ? messages.searchSessions : messages.search,
2028
+ className: classNames?.search,
2029
+ onChange: (query2) => onIntent?.({ type: "change-search", query: query2 })
2030
+ }
2031
+ ) : void 0,
2032
+ actions: showAgents && showSessions || headerActions ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2033
+ showAgents && showSessions ? /* @__PURE__ */ jsxRuntime.jsxs(
2034
+ TabsList,
1744
2035
  {
1745
- ref: searchRef,
1746
- type: "search",
1747
- value: viewModel.searchQuery,
1748
- "aria-label": sessionsOnly ? messages.searchSessions : messages.search,
1749
- placeholder: sessionsOnly ? messages.searchSessions : messages.search,
1750
- className: "min-w-0 [&::-webkit-search-cancel-button]:hidden",
1751
- onChange: (event) => onIntent?.({ type: "change-search", query: event.target.value }),
1752
- onKeyDown: (event) => {
1753
- if (event.key !== "Escape") return;
1754
- onIntent?.({ type: "change-search", query: "" });
1755
- event.currentTarget.blur();
1756
- }
2036
+ className: cn2(
2037
+ "grid min-w-0 flex-1 grid-cols-2 text-foreground",
2038
+ classNames?.tabs
2039
+ ),
2040
+ "aria-label": messages.tabsLabel,
2041
+ children: [
2042
+ /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { value: "agents", children: messages.agents }),
2043
+ /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { value: "sessions", children: messages.sessions })
2044
+ ]
1757
2045
  }
1758
- ),
1759
- viewModel.searchQuery ? /* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxRuntime.jsx(InputGroupButton, { size: "icon-xs", "aria-label": messages.clearSearch, onClick: () => onIntent?.({ type: "change-search", query: "" }), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3.5", "aria-hidden": "true" }) }) }) : /* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "border border-border px-1.5 py-0.5 text-[10px]", children: "Ctrl K" }) })
1760
- ] }) : void 0,
1761
- actions: showAgents && showSessions || headerActions ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1762
- showAgents && showSessions ? /* @__PURE__ */ jsxRuntime.jsxs(TabsList, { className: cn2("grid min-w-0 flex-1 grid-cols-2 text-foreground", classNames?.tabs), "aria-label": messages.tabsLabel, children: [
1763
- /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { value: "agents", children: messages.agents }),
1764
- /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { value: "sessions", children: messages.sessions })
1765
- ] }) : null,
2046
+ ) : null,
1766
2047
  headerActions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center", children: headerActions }) : null
1767
2048
  ] }) : void 0,
1768
- footer: visibleSections.has("footer") && (!sessionsOnly && viewModel.capabilities.manageAgentSettings || footer) ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn2("border-t border-border p-4", classNames?.footer), children: [
1769
- !sessionsOnly && viewModel.capabilities.manageAgentSettings ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", className: "h-10 w-full justify-start gap-2 px-3 text-sm", onClick: () => onIntent?.({ type: "open-agent-settings" }), children: [
1770
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "size-4", "aria-hidden": "true" }),
1771
- messages.settings
1772
- ] }) : null,
1773
- footer
1774
- ] }) : void 0,
2049
+ footer: visibleSections.has("footer") && (!sessionsOnly && viewModel.capabilities.manageAgentSettings || footer) ? /* @__PURE__ */ jsxRuntime.jsxs(
2050
+ "div",
2051
+ {
2052
+ className: cn2("border-t border-border p-4", classNames?.footer),
2053
+ children: [
2054
+ !sessionsOnly && viewModel.capabilities.manageAgentSettings ? /* @__PURE__ */ jsxRuntime.jsxs(
2055
+ Button,
2056
+ {
2057
+ type: "button",
2058
+ variant: "ghost",
2059
+ className: "h-10 w-full justify-start gap-2 px-3 text-sm",
2060
+ onClick: () => onIntent?.({ type: "open-agent-settings" }),
2061
+ children: [
2062
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "size-4", "aria-hidden": "true" }),
2063
+ messages.settings
2064
+ ]
2065
+ }
2066
+ ) : null,
2067
+ footer
2068
+ ]
2069
+ }
2070
+ ) : void 0,
1775
2071
  bodyScrollable: false,
1776
2072
  className,
1777
- classNames: { root: classNames?.root, body: "flex min-h-0 flex-1 flex-col p-0" },
2073
+ classNames: {
2074
+ root: classNames?.root,
2075
+ body: "flex min-h-0 flex-1 flex-col p-0"
2076
+ },
1778
2077
  children: [
1779
- showAgents ? /* @__PURE__ */ jsxRuntime.jsxs(TabsContent, { value: "agents", "data-agent-workbench-scroll-region": true, className: cn2("mt-0 min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain px-4 pb-4", classNames?.body), children: [
1780
- viewModel.capabilities.createAgent ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", className: "mb-3 h-9 w-full justify-start gap-2 px-3 text-sm", onClick: () => onIntent?.({ type: "create-agent" }), children: [
1781
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "size-4", "aria-hidden": "true" }),
1782
- messages.newAgent
1783
- ] }) : null,
1784
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 px-3 text-xs font-medium text-muted-foreground", children: messages.allAgents }),
1785
- /* @__PURE__ */ jsxRuntime.jsx(CollectionState, { status: viewModel.agents.status, empty: messages.emptyAgents, noResults: messages.noResults, hasItems: agents.length > 0, query, error: viewModel.agents.error, onRetry: () => onIntent?.({ type: "retry-agents" }) }),
1786
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: agents.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
1787
- "div",
1788
- {
1789
- "aria-current": item.id === viewModel.selectedAgentItem ? "page" : void 0,
1790
- className: cn2("group flex w-full min-w-0 items-center gap-3 rounded-lg border border-transparent px-3 py-2 text-left hover:bg-muted aria-[current=page]:border-primary aria-[current=page]:bg-muted", classNames?.item),
1791
- children: [
1792
- /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", title: item.name, className: "flex min-w-0 flex-1 items-center gap-3 text-left", onClick: () => onIntent?.({ type: "select-agent", itemId: item.id }), children: [
1793
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(ItemAvatar, { item }) }),
1794
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
1795
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-sm font-medium", children: item.name }),
1796
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-xs text-foreground/80", children: item.description || messages.noDescription })
1797
- ] })
1798
- ] }),
1799
- item.builtIn ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 rounded-full bg-muted px-1.5 py-1 text-[10px] text-foreground", children: messages.builtIn }) : null,
1800
- viewModel.capabilities.pinAgents ? /* @__PURE__ */ jsxRuntime.jsx(
1801
- Button,
1802
- {
1803
- type: "button",
1804
- variant: "ghost",
1805
- size: "icon",
1806
- "aria-label": item.pinned ? messages.unpin : messages.pin,
1807
- className: cn2("size-8 text-muted-foreground opacity-0 group-hover:opacity-100", item.pinned && "text-primary opacity-100"),
1808
- onClick: (event) => {
1809
- event.stopPropagation();
1810
- onIntent?.({ type: "toggle-agent-pin", itemId: item.id, pinned: !item.pinned });
1811
- },
1812
- onKeyDown: (event) => {
1813
- if (event.key === "Enter" || event.key === " ") {
1814
- event.preventDefault();
1815
- event.stopPropagation();
1816
- onIntent?.({ type: "toggle-agent-pin", itemId: item.id, pinned: !item.pinned });
2078
+ showAgents ? /* @__PURE__ */ jsxRuntime.jsxs(
2079
+ TabsContent,
2080
+ {
2081
+ value: "agents",
2082
+ "data-agent-workbench-scroll-region": true,
2083
+ className: cn2(
2084
+ "mt-0 min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain px-4 pb-4",
2085
+ classNames?.body
2086
+ ),
2087
+ children: [
2088
+ viewModel.capabilities.createAgent ? /* @__PURE__ */ jsxRuntime.jsxs(
2089
+ Button,
2090
+ {
2091
+ type: "button",
2092
+ variant: "ghost",
2093
+ className: "mb-3 h-9 w-full justify-start gap-2 px-3 text-sm",
2094
+ onClick: () => onIntent?.({ type: "create-agent" }),
2095
+ children: [
2096
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "size-4", "aria-hidden": "true" }),
2097
+ messages.newAgent
2098
+ ]
2099
+ }
2100
+ ) : null,
2101
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 px-3 text-xs font-medium text-muted-foreground", children: messages.allAgents }),
2102
+ /* @__PURE__ */ jsxRuntime.jsx(
2103
+ CollectionState,
2104
+ {
2105
+ status: viewModel.agents.status,
2106
+ empty: messages.emptyAgents,
2107
+ noResults: messages.noResults,
2108
+ hasItems: agents.length > 0,
2109
+ query,
2110
+ error: viewModel.agents.error,
2111
+ onRetry: () => onIntent?.({ type: "retry-agents" })
2112
+ }
2113
+ ),
2114
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: agents.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
2115
+ "div",
2116
+ {
2117
+ "aria-current": item.id === viewModel.selectedAgentItem ? "page" : void 0,
2118
+ className: cn2(
2119
+ "group flex w-full min-w-0 items-center gap-3 rounded-lg border border-transparent px-3 py-2 text-left hover:bg-muted aria-[current=page]:border-primary aria-[current=page]:bg-muted",
2120
+ classNames?.item
2121
+ ),
2122
+ children: [
2123
+ /* @__PURE__ */ jsxRuntime.jsxs(
2124
+ "button",
2125
+ {
2126
+ type: "button",
2127
+ title: item.name,
2128
+ className: "flex min-w-0 flex-1 items-center gap-3 text-left",
2129
+ onClick: () => onIntent?.({ type: "select-agent", itemId: item.id }),
2130
+ children: [
2131
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(ItemAvatar, { item }) }),
2132
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
2133
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-sm font-medium", children: item.name }),
2134
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-xs text-foreground/80", children: item.description || messages.noDescription })
2135
+ ] })
2136
+ ]
1817
2137
  }
1818
- },
1819
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pin, { className: cn2("size-4", item.pinned && "fill-current", item.pinPending && "animate-pulse") })
1820
- }
1821
- ) : null
1822
- ]
1823
- },
1824
- item.id
1825
- )) })
1826
- ] }) : null,
1827
- showSessions ? /* @__PURE__ */ jsxRuntime.jsxs(TabsContent, { value: "sessions", "data-agent-workbench-scroll-region": true, className: cn2("mt-0 min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain px-4 pb-4", classNames?.body), children: [
1828
- visibleSections.has("new-session") && viewModel.capabilities.createSession ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", className: "h-9 w-full justify-start gap-2 px-3 text-sm", onClick: () => onIntent?.({ type: "create-session" }), children: [
1829
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SquarePen, { className: "size-4", "aria-hidden": "true" }),
1830
- messages.newSession
1831
- ] }) : null,
1832
- !sessionsOnly && viewModel.capabilities.manageCapabilities ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", className: "mb-3 h-9 w-full justify-start gap-2 px-3 text-sm", onClick: () => onIntent?.({ type: "open-capabilities" }), children: [
1833
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Blocks, { className: "size-4", "aria-hidden": "true" }),
1834
- messages.capabilities
1835
- ] }) : null,
1836
- !sessionsOnly ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 px-3 text-xs font-medium text-muted-foreground", children: messages.recentSessions }) : null,
1837
- /* @__PURE__ */ jsxRuntime.jsx(CollectionState, { status: viewModel.sessions.status, empty: messages.emptySessions, noResults: messages.noResults, hasItems: sessions.length > 0, query, error: viewModel.sessions.error, onRetry: () => onIntent?.({ type: "retry-sessions" }) }),
1838
- sessionsOnly && sessions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: [
1839
- { id: "chatbot", label: messages.chats, icon: lucideReact.MessageSquare, items: chatbotSessions },
1840
- { id: "agent", label: messages.agents, icon: lucideReact.Bot, items: agentSessions }
1841
- ].map(({ id, label, icon: Icon2, items }) => /* @__PURE__ */ jsxRuntime.jsxs("details", { open: true, "aria-label": label, children: [
1842
- /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex h-9 cursor-pointer list-none items-center gap-2 rounded-md px-3 text-sm font-semibold hover:bg-muted", children: [
1843
- /* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
1844
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: label })
1845
- ] }),
1846
- renderSessionItems(items)
1847
- ] }, id)) }) : !sessionsOnly ? renderSessionItems(sessions) : null
1848
- ] }) : null
2138
+ ),
2139
+ item.builtIn ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 rounded-full bg-muted px-1.5 py-1 text-[10px] text-foreground", children: messages.builtIn }) : null,
2140
+ viewModel.capabilities.pinAgents ? /* @__PURE__ */ jsxRuntime.jsx(
2141
+ Button,
2142
+ {
2143
+ type: "button",
2144
+ variant: "ghost",
2145
+ size: "icon",
2146
+ "aria-label": item.pinned ? messages.unpin : messages.pin,
2147
+ className: cn2(
2148
+ "size-8 text-muted-foreground opacity-0 group-hover:opacity-100",
2149
+ item.pinned && "text-primary opacity-100"
2150
+ ),
2151
+ onClick: (event) => {
2152
+ event.stopPropagation();
2153
+ onIntent?.({
2154
+ type: "toggle-agent-pin",
2155
+ itemId: item.id,
2156
+ pinned: !item.pinned
2157
+ });
2158
+ },
2159
+ onKeyDown: (event) => {
2160
+ if (event.key === "Enter" || event.key === " ") {
2161
+ event.preventDefault();
2162
+ event.stopPropagation();
2163
+ onIntent?.({
2164
+ type: "toggle-agent-pin",
2165
+ itemId: item.id,
2166
+ pinned: !item.pinned
2167
+ });
2168
+ }
2169
+ },
2170
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2171
+ lucideReact.Pin,
2172
+ {
2173
+ className: cn2(
2174
+ "size-4",
2175
+ item.pinned && "fill-current",
2176
+ item.pinPending && "animate-pulse"
2177
+ )
2178
+ }
2179
+ )
2180
+ }
2181
+ ) : null
2182
+ ]
2183
+ },
2184
+ item.id
2185
+ )) })
2186
+ ]
2187
+ }
2188
+ ) : null,
2189
+ showSessions ? /* @__PURE__ */ jsxRuntime.jsxs(
2190
+ TabsContent,
2191
+ {
2192
+ value: "sessions",
2193
+ "data-agent-workbench-scroll-region": true,
2194
+ className: cn2(
2195
+ "mt-0 min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain px-4 pb-4",
2196
+ classNames?.body
2197
+ ),
2198
+ children: [
2199
+ visibleSections.has("new-session") && viewModel.capabilities.createSession ? /* @__PURE__ */ jsxRuntime.jsx(
2200
+ AgentWorkbenchSidebarNewSessionButton,
2201
+ {
2202
+ label: messages.newSession,
2203
+ onClick: () => onIntent?.({ type: "create-session" })
2204
+ }
2205
+ ) : null,
2206
+ !sessionsOnly && viewModel.capabilities.manageCapabilities ? /* @__PURE__ */ jsxRuntime.jsxs(
2207
+ Button,
2208
+ {
2209
+ type: "button",
2210
+ variant: "ghost",
2211
+ className: "mb-3 h-9 w-full justify-start gap-2 px-3 text-sm",
2212
+ onClick: () => onIntent?.({ type: "open-capabilities" }),
2213
+ children: [
2214
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Blocks, { className: "size-4", "aria-hidden": "true" }),
2215
+ messages.capabilities
2216
+ ]
2217
+ }
2218
+ ) : null,
2219
+ /* @__PURE__ */ jsxRuntime.jsx(
2220
+ AgentWorkbenchSessionList,
2221
+ {
2222
+ sessions,
2223
+ selectedSessionId: viewModel.selectedSessionItem,
2224
+ status: viewModel.sessions.status,
2225
+ error: viewModel.sessions.error,
2226
+ query,
2227
+ emptyLabel: messages.emptySessions,
2228
+ noResultsLabel: messages.noResults,
2229
+ groupByMode: sessionsOnly,
2230
+ showHeading: !sessionsOnly,
2231
+ itemClassName: classNames?.item,
2232
+ capabilities: {
2233
+ pin: viewModel.capabilities.pinSessions,
2234
+ rename: viewModel.capabilities.renameSessions,
2235
+ delete: viewModel.capabilities.deleteSessions
2236
+ },
2237
+ onSelect: (sessionId) => onIntent?.({ type: "select-session", sessionId }),
2238
+ onTogglePin: (sessionId, pinned) => onIntent?.({ type: "toggle-session-pin", sessionId, pinned }),
2239
+ onRename: (sessionId, title) => onIntent?.({ type: "rename-session", sessionId, title }),
2240
+ onDelete: (sessionId) => onIntent?.({ type: "delete-session", sessionId }),
2241
+ onRetry: () => onIntent?.({ type: "retry-sessions" })
2242
+ }
2243
+ )
2244
+ ]
2245
+ }
2246
+ ) : null
1849
2247
  ]
1850
2248
  }
1851
2249
  )
@@ -1919,9 +2317,10 @@ function AgentWorkbenchExploreSidebar({
1919
2317
  renderItemMedia,
1920
2318
  onIntent
1921
2319
  }) {
1922
- const navigationMessages = useMonkeysLocaleMessages().agentWorkbench.navigation;
1923
- const searchRef = React5.useRef(null);
1924
- const resolvedConfig = React5.useMemo(() => monkeys.resolveAgentWorkbenchSidebarConfig(config), [config]);
2320
+ const resolvedConfig = React5.useMemo(
2321
+ () => monkeys.resolveAgentWorkbenchSidebarConfig(config),
2322
+ [config]
2323
+ );
1925
2324
  const visibleSections = React5.useMemo(
1926
2325
  () => new Set(resolvedConfig.visibleSections),
1927
2326
  [resolvedConfig.visibleSections]
@@ -1944,28 +2343,18 @@ function AgentWorkbenchExploreSidebar({
1944
2343
  if (groups.some((group) => group.id === activeGroupId)) return;
1945
2344
  setActiveGroupId(resolvedDefaultGroupId ?? groups[0]?.id ?? "");
1946
2345
  }, [activeGroupId, groups, resolvedDefaultGroupId]);
1947
- React5.useEffect(() => {
1948
- const handleShortcut = (event) => {
1949
- if (!(event.ctrlKey || event.metaKey) || event.key.toLocaleLowerCase() !== "k")
1950
- return;
1951
- event.preventDefault();
1952
- searchRef.current?.focus();
1953
- searchRef.current?.select();
1954
- };
1955
- window.addEventListener("keydown", handleShortcut);
1956
- return () => window.removeEventListener("keydown", handleShortcut);
1957
- }, []);
1958
2346
  const changeGroup = (groupId) => {
1959
2347
  setActiveGroupId(groupId);
1960
2348
  onIntent?.({ type: "change-group", groupId });
1961
2349
  };
1962
- const state = !visibleSections.has("sessions") ? "ready" : error ? "error" : loading && sessions.length === 0 ? "loading" : filteredSessions.length === 0 && !draftVisible ? "empty" : "ready";
1963
2350
  const groupNavigation = visibleSections.has("groups") && activeGroup ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border px-4 pb-4 pt-3", children: /* @__PURE__ */ jsxRuntime.jsxs(Tabs, { value: activeGroup.id, onValueChange: changeGroup, children: [
1964
2351
  /* @__PURE__ */ jsxRuntime.jsx(
1965
2352
  TabsList,
1966
2353
  {
1967
2354
  className: "grid h-10 w-full rounded-[var(--radius)] bg-muted p-0.5 text-foreground",
1968
- style: { gridTemplateColumns: `repeat(${groups.length}, minmax(0, 1fr))` },
2355
+ style: {
2356
+ gridTemplateColumns: `repeat(${groups.length}, minmax(0, 1fr))`
2357
+ },
1969
2358
  children: groups.map((group) => /* @__PURE__ */ jsxRuntime.jsx(
1970
2359
  TabsTrigger,
1971
2360
  {
@@ -1984,7 +2373,11 @@ function AgentWorkbenchExploreSidebar({
1984
2373
  "aria-label": item.title,
1985
2374
  className: "group relative aspect-[1.27] overflow-hidden rounded-[var(--radius)] border border-border bg-card text-left transition hover:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1986
2375
  style: Number.isFinite(group.itemAspectRatio) && Number(group.itemAspectRatio) > 0 ? { aspectRatio: group.itemAspectRatio } : void 0,
1987
- onClick: () => onIntent?.({ type: "select-item", groupId: group.id, item }),
2376
+ onClick: () => onIntent?.({
2377
+ type: "select-item",
2378
+ groupId: group.id,
2379
+ item
2380
+ }),
1988
2381
  children: renderItemMedia?.(item, group) ?? /* @__PURE__ */ jsxRuntime.jsx(AgentWorkbenchExploreCardMedia, { item })
1989
2382
  },
1990
2383
  item.id
@@ -1997,47 +2390,23 @@ function AgentWorkbenchExploreSidebar({
1997
2390
  "data-sidebar-width-percent": resolvedConfig.widthPercent,
1998
2391
  "aria-label": labels.navigation,
1999
2392
  header: visibleSections.has("header") ? header : void 0,
2000
- search: visibleSections.has("search") ? /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { className: "h-12 rounded-[var(--radius)] border-border bg-card text-foreground", children: [
2001
- /* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "size-4 text-muted-foreground", "aria-hidden": "true" }) }),
2002
- /* @__PURE__ */ jsxRuntime.jsx(
2003
- InputGroupInput,
2004
- {
2005
- ref: searchRef,
2006
- type: "search",
2007
- value: searchQuery,
2008
- "aria-label": labels.search,
2009
- placeholder: labels.search,
2010
- className: "min-w-0 text-foreground placeholder:text-muted-foreground [&::-webkit-search-cancel-button]:hidden",
2011
- onChange: (event) => onIntent?.({ type: "change-search", query: event.target.value })
2012
- }
2013
- ),
2014
- /* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "rounded-sm border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground", children: "Ctrl K" }) })
2015
- ] }) : void 0,
2016
- primaryAction: visibleSections.has("new-session") ? /* @__PURE__ */ jsxRuntime.jsxs(
2017
- Button,
2393
+ search: visibleSections.has("search") ? /* @__PURE__ */ jsxRuntime.jsx(
2394
+ AgentWorkbenchSidebarSearch,
2018
2395
  {
2019
- type: "button",
2020
- className: "h-11 w-full justify-start gap-2 rounded-[var(--radius)] border border-primary/60 bg-primary px-3 font-semibold text-primary-foreground hover:bg-primary/90",
2021
- onClick: () => onIntent?.({ type: "create-session" }),
2022
- children: [
2023
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SquarePen, { className: "size-4", "aria-hidden": "true" }),
2024
- labels.newSession
2025
- ]
2396
+ value: searchQuery,
2397
+ label: labels.search,
2398
+ onChange: (query) => onIntent?.({ type: "change-search", query })
2399
+ }
2400
+ ) : void 0,
2401
+ primaryAction: visibleSections.has("new-session") ? /* @__PURE__ */ jsxRuntime.jsx(
2402
+ AgentWorkbenchSidebarNewSessionButton,
2403
+ {
2404
+ label: labels.newSession,
2405
+ onClick: () => onIntent?.({ type: "create-session" })
2026
2406
  }
2027
2407
  ) : void 0,
2028
2408
  groups: groupNavigation,
2029
2409
  footer: visibleSections.has("footer") ? footer : void 0,
2030
- status: state,
2031
- loadingState: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-24 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-5 animate-spin" }) }),
2032
- emptyState: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-8 text-center text-sm text-muted-foreground", children: normalizedQuery ? labels.noResults : labels.emptySessions }),
2033
- errorState: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-24 flex-col items-center justify-center gap-2 px-3 py-6 text-center", role: "alert", children: [
2034
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "size-5 shrink-0 text-destructive-text", "aria-hidden": "true" }),
2035
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-full break-words text-sm text-muted-foreground", children: error }),
2036
- labels.retry ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", className: "gap-1.5 text-primary", onClick: () => onIntent?.({ type: "retry-sessions" }), children: [
2037
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "size-3.5", "aria-hidden": "true" }),
2038
- labels.retry
2039
- ] }) : null
2040
- ] }),
2041
2410
  bodyProps: { "data-agent-workbench-session-scroll-region": "" },
2042
2411
  className,
2043
2412
  classNames: { body: "min-h-[160px] flex-[0_1_280px] px-4 pb-3" },
@@ -2052,53 +2421,24 @@ function AgentWorkbenchExploreSidebar({
2052
2421
  children: labels.draftSession
2053
2422
  }
2054
2423
  ) : null,
2055
- filteredSessions.map((session) => /* @__PURE__ */ jsxRuntime.jsxs(
2056
- "div",
2424
+ filteredSessions.length > 0 || !draftVisible || loading || error ? /* @__PURE__ */ jsxRuntime.jsx(
2425
+ AgentWorkbenchSessionList,
2057
2426
  {
2058
- "aria-current": session.id === selectedSessionId ? "page" : void 0,
2059
- className: "group flex h-10 w-full min-w-0 items-center rounded-[var(--radius)] border border-transparent bg-muted/60 text-foreground transition hover:bg-muted aria-[current=page]:border-primary aria-[current=page]:bg-primary/10",
2060
- children: [
2061
- /* @__PURE__ */ jsxRuntime.jsx(
2062
- "button",
2063
- {
2064
- type: "button",
2065
- title: session.title,
2066
- className: "h-full min-w-0 flex-1 truncate px-3 text-left text-sm font-semibold",
2067
- onClick: () => onIntent?.({ type: "select-session", sessionId: session.id }),
2068
- children: session.title
2069
- }
2070
- ),
2071
- deleteSessions ? /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu2, { children: [
2072
- /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
2073
- Button,
2074
- {
2075
- type: "button",
2076
- variant: "ghost",
2077
- size: "icon",
2078
- "aria-label": navigationMessages.actions,
2079
- className: "mr-1 size-8 shrink-0 text-muted-foreground opacity-0 transition-opacity group-aria-[current=page]:opacity-100 group-focus-within:opacity-100 group-hover:opacity-100 data-[state=open]:opacity-100",
2080
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ellipsis, { className: "size-4", "aria-hidden": "true" })
2081
- }
2082
- ) }),
2083
- /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuContent, { align: "end", children: /* @__PURE__ */ jsxRuntime.jsxs(
2084
- DropdownMenuItem,
2085
- {
2086
- className: "text-destructive-text",
2087
- onSelect: () => onIntent?.({
2088
- type: "delete-session",
2089
- sessionId: session.id
2090
- }),
2091
- children: [
2092
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "mr-2 size-4", "aria-hidden": "true" }),
2093
- navigationMessages.delete
2094
- ]
2095
- }
2096
- ) })
2097
- ] }) : null
2098
- ]
2099
- },
2100
- session.id
2101
- ))
2427
+ sessions: filteredSessions,
2428
+ selectedSessionId,
2429
+ status: error ? "error" : loading ? "loading" : "ready",
2430
+ error,
2431
+ query: normalizedQuery,
2432
+ emptyLabel: labels.emptySessions,
2433
+ noResultsLabel: labels.noResults,
2434
+ retryLabel: labels.retry,
2435
+ groupByMode: resolvedConfig.navigationMode !== "default",
2436
+ capabilities: { delete: deleteSessions },
2437
+ onSelect: (sessionId) => onIntent?.({ type: "select-session", sessionId }),
2438
+ onDelete: (sessionId) => onIntent?.({ type: "delete-session", sessionId }),
2439
+ onRetry: labels.retry ? () => onIntent?.({ type: "retry-sessions" }) : void 0
2440
+ }
2441
+ ) : null
2102
2442
  ] }) : null
2103
2443
  }
2104
2444
  );