Kill off agents pane now that we have FAB (#6613)

# Description of Changes
Kill off agents pane now that we have the FAB. Also fixes a bug with the
FAB where it would sometimes fail to render the chat, and fixes a
duplicated entry in the Vite config which was throwing a warning
This commit is contained in:
James Brunton
2026-06-11 17:28:05 +01:00
committed by GitHub
parent 5bc7ae626d
commit 34ead60194
12 changed files with 58 additions and 1006 deletions
@@ -1,43 +0,0 @@
/**
* Core stubs for the right-rail Agents UI.
*
* The real implementations live in {@code proprietary/components/agents/AgentsPanel.tsx}
* and shadow these stubs via the {@code @app/*} alias cascade when the proprietary
* build is active. Core builds render nothing, so the right rail collapses to the
* tool list unchanged.
*/
/** Whether the right rail should reserve space for agents UI. False in core. */
export function useAgentsEnabled(): boolean {
return false;
}
/**
* Whether the agent chat panel is currently open. Core builds have no chat,
* so this always returns false. Proprietary builds bridge to the ChatContext.
*/
export function useAgentChatOpen(): boolean {
return false;
}
/** Inline "Agents" section rendered above the tool list in {@code ToolPicker}. */
export function AgentsSection() {
return null;
}
/**
* Icon-only agent button rendered in the collapsed (minimised) right rail.
* Returns null in core; proprietary renders the Stirling agent shortcut.
*/
export function AgentsCollapsedButton(_props: { onExpand: () => void }) {
return null;
}
/**
* Agents card rendered inside the fullscreen tool picker. Matches the visual
* language of the fullscreen category cards (gradient border, title, items).
* Returns null in core; proprietary renders the Stirling agent.
*/
export function AgentsFullscreenSection() {
return null;
}
@@ -7,12 +7,9 @@
export function useChat() {
return {
messages: [] as never[],
isOpen: false,
isLoading: false,
progress: null,
progressLog: [] as never[],
toggleOpen: () => {},
setOpen: (_open: boolean) => {},
sendMessage: async (_content: string) => {},
clearChat: () => {},
};
@@ -3,11 +3,6 @@ import { useToolWorkflow } from "@app/contexts/ToolWorkflowContext";
import { useIsMobile } from "@app/hooks/useIsMobile";
import { usePreferences } from "@app/contexts/PreferencesContext";
import { useWorkbenchBar } from "@app/contexts/WorkbenchBarContext";
import {
AgentsFullscreenSection,
useAgentChatOpen,
useAgentsEnabled,
} from "@app/components/agents/AgentsPanel";
import FullscreenToolSurface from "@app/components/tools/FullscreenToolSurface";
import { ToolId } from "@app/types/toolId";
import type { ToolPanelGeometry } from "@app/hooks/tools/useToolPanelGeometry";
@@ -16,13 +11,11 @@ import type { ToolPanelGeometry } from "@app/hooks/tools/useToolPanelGeometry";
export function useIsFullscreenExpanded(): boolean {
const { toolPanelMode, leftPanelView, readerMode } = useToolWorkflow();
const isMobile = useIsMobile();
const agentChatOpen = useAgentChatOpen();
return (
toolPanelMode === "fullscreen" &&
leftPanelView === "toolPicker" &&
!isMobile &&
!readerMode &&
!agentChatOpen
!readerMode
);
}
@@ -50,8 +43,6 @@ export function FullscreenToolPanel({ geometry }: FullscreenToolPanelProps) {
handleToolSelect,
} = useToolWorkflow();
const isMobile = useIsMobile();
const agentsEnabled = useAgentsEnabled();
const agentChatOpen = useAgentChatOpen();
const { setAllButtonsDisabled } = useWorkbenchBar();
const { preferences, updatePreference } = usePreferences();
@@ -59,8 +50,7 @@ export function FullscreenToolPanel({ geometry }: FullscreenToolPanelProps) {
toolPanelMode === "fullscreen" &&
leftPanelView === "toolPicker" &&
!isMobile &&
!readerMode &&
!agentChatOpen;
!readerMode;
useEffect(() => {
setAllButtonsDisabled(fullscreenExpanded);
@@ -94,9 +84,6 @@ export function FullscreenToolPanel({ geometry }: FullscreenToolPanelProps) {
}
onExitFullscreenMode={() => setToolPanelMode("sidebar")}
geometry={geometry}
agentsSlot={
agentsEnabled && !searchQuery ? <AgentsFullscreenSection /> : null
}
/>
);
}
@@ -25,8 +25,6 @@ interface FullscreenToolSurfaceProps {
onToggleDescriptions: () => void;
onExitFullscreenMode: () => void;
geometry: ToolPanelGeometry | null;
/** Optional agents block rendered above the tool list. */
agentsSlot?: React.ReactNode;
}
const FullscreenToolSurface = ({
@@ -41,7 +39,6 @@ const FullscreenToolSurface = ({
onToggleDescriptions,
onExitFullscreenMode: _onExitFullscreenMode,
geometry,
agentsSlot,
}: FullscreenToolSurfaceProps) => {
const { t } = useTranslation();
const surfaceRef = useRef<HTMLDivElement>(null);
@@ -92,9 +89,6 @@ const FullscreenToolSurface = ({
className="tool-panel__fullscreen-scroll"
offsetScrollbars
>
{agentsSlot && (
<div className="tool-panel__fullscreen-agents">{agentsSlot}</div>
)}
<FullscreenToolList
filteredTools={filteredTools}
searchQuery={searchQuery}
@@ -1,4 +1,4 @@
import { useMemo, useState, useRef, useCallback } from "react";
import { useMemo, useState } from "react";
import { ActionIcon } from "@mantine/core";
import { useTranslation } from "react-i18next";
import { useRainbowThemeContext } from "@app/components/shared/RainbowThemeProvider";
@@ -8,11 +8,6 @@ import rainbowStyles from "@app/styles/rainbow.module.css";
import { useIsMobile } from "@app/hooks/useIsMobile";
import ToolPanel from "@app/components/tools/ToolPanel";
import ToolSearch from "@app/components/tools/toolPicker/ToolSearch";
import {
AgentsCollapsedButton,
AgentsSection,
useAgentsEnabled,
} from "@app/components/agents/AgentsPanel";
import {
PoliciesCollapsedButton,
PoliciesSection,
@@ -21,8 +16,6 @@ import {
usePolicyDetailActive,
} from "@app/components/policies/PoliciesSidebar";
import { PolicyAutoRunController } from "@app/components/policies/PolicyAutoRunController";
import { useChat } from "@app/components/chat/ChatContext";
import { ChatPanel } from "@app/components/chat/ChatPanel";
import { useFavoriteToolItems } from "@app/hooks/tools/useFavoriteToolItems";
import { useToolSections } from "@app/hooks/useToolSections";
import type { SubcategoryGroup } from "@app/hooks/useToolSections";
@@ -41,16 +34,12 @@ import {
import { useToolPanelGeometry } from "@app/hooks/tools/useToolPanelGeometry";
import "@app/components/tools/ToolPanel.css";
const DEFAULT_CHAT_WIDTH_PX = 18.5 * 16; // 18.5rem in px
const MIN_CHAT_WIDTH_PX = 240;
const MAX_CHAT_WIDTH_PX = 720;
/**
* Right-side rail wrapping the tool panel.
*
* Owns the rail-level concerns: collapse/expand chrome, the AGENTS top label,
* the collapsed strip (agent button + favourite/recommended icon shortcuts),
* and the agents chat overlay. Fullscreen takeover lives in FullscreenToolPanel.
* Owns the rail-level concerns: collapse/expand chrome and the collapsed strip
* (favourite/recommended icon shortcuts). Fullscreen takeover lives in
* FullscreenToolPanel.
*/
export default function RightSidebar() {
const { t } = useTranslation();
@@ -77,7 +66,6 @@ export default function RightSidebar() {
favoriteTools,
} = useToolWorkflow();
const agentsEnabled = useAgentsEnabled();
const policiesEnabled = usePoliciesEnabled();
const rawPolicyDetailActive = usePolicyDetailActive();
const fullscreenExpanded = useIsFullscreenExpanded();
@@ -101,57 +89,6 @@ export default function RightSidebar() {
const [allToolsView, setAllToolsView] = useState(false);
const { isOpen: isChatOpen, setOpen: setChatOpen } = useChat();
const [chatWidthPx, setChatWidthPx] = useState(DEFAULT_CHAT_WIDTH_PX);
const [isChatDragging, setIsChatDragging] = useState(false);
const chatDragState = useRef<{ startX: number; startWidth: number } | null>(
null,
);
const handleChatClose = useCallback(() => {
withViewTransition(() => setChatOpen(false));
setChatWidthPx(DEFAULT_CHAT_WIDTH_PX);
}, [setChatOpen]);
const handleResizeChatPointerDown = useCallback(
(e: React.PointerEvent<HTMLDivElement>) => {
e.preventDefault();
chatDragState.current = { startX: e.clientX, startWidth: chatWidthPx };
setIsChatDragging(true);
document.body.style.cursor = "col-resize";
document.body.style.userSelect = "none";
const onMove = (ev: PointerEvent) => {
if (!chatDragState.current) return;
const delta = chatDragState.current.startX - ev.clientX;
setChatWidthPx(
Math.max(
MIN_CHAT_WIDTH_PX,
Math.min(
MAX_CHAT_WIDTH_PX,
chatDragState.current.startWidth + delta,
),
),
);
};
const cleanup = () => {
chatDragState.current = null;
setIsChatDragging(false);
document.body.style.removeProperty("cursor");
document.body.style.removeProperty("user-select");
window.removeEventListener("pointermove", onMove);
window.removeEventListener("pointerup", cleanup);
window.removeEventListener("pointercancel", cleanup);
};
window.addEventListener("pointermove", onMove);
window.addEventListener("pointerup", cleanup);
window.addEventListener("pointercancel", cleanup);
},
[chatWidthPx],
);
const handleShowAllTools = () => {
withViewTransition(() => setAllToolsView(true));
};
@@ -186,12 +123,11 @@ export default function RightSidebar() {
policiesEnabled && !allToolsView && leftPanelView === "toolPicker";
// When Policies are shown, the search moves OUT of the header to sit between
// the Policies and Tools sections (separating them); otherwise it stays in the
// header. Show the header search when there's a close button, or when agents
// are off in the default tool-picker view (inline filtering).
// header. Show the header search when there's a close button, or in the
// default tool-picker view.
const showInlineSearch = showPolicies && !showCloseButton;
const showHeaderSearch =
!showInlineSearch &&
(showCloseButton || (!agentsEnabled && leftPanelView === "toolPicker"));
!showInlineSearch && (showCloseButton || leftPanelView === "toolPicker");
const handleHeaderBack = () => {
if (inToolView) {
@@ -224,13 +160,6 @@ export default function RightSidebar() {
? (toolRegistry[selectedToolKey as ToolId] ?? null)
: null;
// Agents header + section is hidden when:
// - the AI engine is off, or
// - the user is in the all-tools view, or
// - a specific tool is being rendered (leftPanelView ≠ "toolPicker").
const showAgents =
agentsEnabled && !allToolsView && leftPanelView === "toolPicker";
// The detail takeover replaces the tool list ONLY in the same default view —
// never over an open tool or the all-tools view (which must keep priority).
// A lingering selection is harmless: it stays hidden behind a tool and the
@@ -243,7 +172,6 @@ export default function RightSidebar() {
const computedWidth = () => {
if (isMobile) return "100%";
if (isChatOpen) return `${chatWidthPx}px`;
if (!isPanelVisible) return "3.5rem";
return expandedWidth;
};
@@ -279,41 +207,17 @@ export default function RightSidebar() {
ref={toolPanelRef}
data-sidebar="tool-panel"
data-tour={fullscreenExpanded ? undefined : "tool-panel"}
className={`tool-panel flex flex-col ${fullscreenExpanded ? "tool-panel--fullscreen-active" : isChatOpen ? "" : "overflow-hidden"} bg-[var(--bg-toolbar)] border-l border-[var(--border-subtle)] transition-all duration-300 ease-out ${
className={`tool-panel flex flex-col ${fullscreenExpanded ? "tool-panel--fullscreen-active" : "overflow-hidden"} bg-[var(--bg-toolbar)] border-l border-[var(--border-subtle)] transition-all duration-300 ease-out ${
isRainbowMode ? rainbowStyles.rainbowPaper : ""
} ${isMobile ? "h-full border-r-0" : "h-screen"} ${fullscreenExpanded ? "tool-panel--fullscreen" : ""}`}
style={{
width: computedWidth(),
padding: "0",
...(isChatDragging ? { transition: "none" } : {}),
}}
>
{/* Headless: enforces enabled policies on every uploaded file. */}
{policiesEnabled && <PolicyAutoRunController />}
{!fullscreenExpanded && isChatOpen && (
<div
style={{
height: "100%",
width: "100%",
display: "flex",
flexDirection: "column",
}}
>
<div
className="agents-takeover__resize-handle"
onPointerDown={handleResizeChatPointerDown}
role="separator"
aria-label={t("chat.resize", "Resize chat panel")}
aria-orientation="vertical"
/>
<ChatPanel
onBack={handleChatClose}
backLabel={t("agents.back_to_tools", "Back to tools")}
/>
</div>
)}
{!fullscreenExpanded && !isChatOpen && !isPanelVisible && !isMobile && (
{!fullscreenExpanded && !isPanelVisible && !isMobile && (
<div className="tool-panel__collapsed-strip">
<div className="tool-panel__collapsed-top">
<ActionIcon
@@ -327,7 +231,6 @@ export default function RightSidebar() {
>
<ChevronLeftIcon sx={{ fontSize: "1.1rem" }} />
</ActionIcon>
<AgentsCollapsedButton onExpand={handleExpand} />
</div>
<div className="tool-panel__collapsed-divider" />
<PoliciesCollapsedButton onExpand={handleOpenPolicy} />
@@ -358,7 +261,7 @@ export default function RightSidebar() {
</div>
)}
{!fullscreenExpanded && !isChatOpen && isPanelVisible && (
{!fullscreenExpanded && isPanelVisible && (
<div
/* Fixed width matches the expanded panel width so the inner content is
laid out at its final size from the moment it mounts. The outer
@@ -409,13 +312,7 @@ export default function RightSidebar() {
autoFocus={allToolsView && !inToolView}
/>
</div>
) : (
showAgents && (
<span className="tool-panel__section-label">
{t("agents.section_title", "Agents")}
</span>
)
)}
) : null}
{showCloseButton ? (
<ActionIcon
variant="subtle"
@@ -447,8 +344,6 @@ export default function RightSidebar() {
</div>
)}
{showAgents && <AgentsSection />}
{showPolicies && (
<PoliciesSection
leadingControl={
@@ -481,7 +376,7 @@ export default function RightSidebar() {
allToolsView={allToolsView}
onShowAllTools={handleShowAllTools}
onToolSelect={handleToolSelectWithTransition}
compact={agentsEnabled && !allToolsView}
compact={false}
/>
</>
)}
@@ -385,15 +385,6 @@
}
}
.tool-panel__section-label {
font-size: 0.7rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-muted);
line-height: 1;
}
.tool-panel__mode-toggle {
transition: transform 0.2s ease;
}
@@ -855,33 +846,6 @@
gap: 0.75rem;
}
/* Agents card lives in its own column above the tool grid. It uses the same
.tool-panel__fullscreen-group base styles but with a colourful gradient
border so it stands out as a distinct surface (and doesn't blend into the
neighbouring category cards). */
.tool-panel__fullscreen-agents {
padding: 1.5rem 1.75rem 0;
}
.tool-panel__fullscreen-group--agents {
position: relative;
background:
linear-gradient(var(--fullscreen-bg-group), var(--fullscreen-bg-group))
padding-box,
linear-gradient(
135deg,
var(--mantine-color-blue-6) 0%,
var(--mantine-color-violet-6) 45%,
var(--mantine-color-pink-6) 100%
)
border-box;
border: 1.5px solid transparent;
}
.tool-panel__fullscreen-section-icon--agents {
color: var(--mantine-color-blue-6);
}
@keyframes tool-panel-fullscreen-slide-in {
from {
transform: translateX(6%) scaleX(0.85);