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