feat(agents): hide archived agents from default list (#373)

* feat(agents): hide archived agents from default list

Archived agents are now filtered out of the default agent list view.
A toggle button (archive icon) appears when archived agents exist,
allowing users to switch between viewing active and archived agents.
The @mention suggestion list already filters out archived agents.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(agents): show "No active agents" when all agents are archived

When there are archived agents but no active ones, the empty state now
shows "No active agents" instead of "No agents yet" to avoid confusion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Devv <devv@Devvs-Mac-mini.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
devv-eve 2026-04-02 22:59:36 -07:00 committed by GitHub
parent 978e81a268
commit 7b610a4013
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import { useState, useEffect, useRef } from "react"; import { useState, useEffect, useRef, useMemo } from "react";
import { useDefaultLayout } from "react-resizable-panels"; import { useDefaultLayout } from "react-resizable-panels";
import { import {
Bot, Bot,
@ -29,6 +29,7 @@ import {
Lock, Lock,
Settings, Settings,
Camera, Camera,
Archive,
} from "lucide-react"; } from "lucide-react";
import type { import type {
Agent, Agent,
@ -1546,6 +1547,7 @@ export default function AgentsPage() {
const agents = useWorkspaceStore((s) => s.agents); const agents = useWorkspaceStore((s) => s.agents);
const refreshAgents = useWorkspaceStore((s) => s.refreshAgents); const refreshAgents = useWorkspaceStore((s) => s.refreshAgents);
const [selectedId, setSelectedId] = useState<string>(""); const [selectedId, setSelectedId] = useState<string>("");
const [showArchived, setShowArchived] = useState(false);
const [showCreate, setShowCreate] = useState(false); const [showCreate, setShowCreate] = useState(false);
const runtimes = useRuntimeStore((s) => s.runtimes); const runtimes = useRuntimeStore((s) => s.runtimes);
const fetchRuntimes = useRuntimeStore((s) => s.fetchRuntimes); const fetchRuntimes = useRuntimeStore((s) => s.fetchRuntimes);
@ -1557,12 +1559,19 @@ export default function AgentsPage() {
if (workspace) fetchRuntimes(); if (workspace) fetchRuntimes();
}, [workspace, fetchRuntimes]); }, [workspace, fetchRuntimes]);
// Select first agent on initial load const filteredAgents = useMemo(
() => showArchived ? agents.filter((a) => !!a.archived_at) : agents.filter((a) => !a.archived_at),
[agents, showArchived],
);
const archivedCount = useMemo(() => agents.filter((a) => !!a.archived_at).length, [agents]);
// Select first agent on initial load or when filter changes
useEffect(() => { useEffect(() => {
if (agents.length > 0 && !selectedId) { if (filteredAgents.length > 0 && !filteredAgents.some((a) => a.id === selectedId)) {
setSelectedId(agents[0]!.id); setSelectedId(filteredAgents[0]!.id);
} }
}, [agents, selectedId]); }, [filteredAgents, selectedId]);
const handleCreate = async (data: CreateAgentRequest) => { const handleCreate = async (data: CreateAgentRequest) => {
const agent = await api.createAgent(data); const agent = await api.createAgent(data);
@ -1655,30 +1664,46 @@ export default function AgentsPage() {
<div className="overflow-y-auto h-full border-r"> <div className="overflow-y-auto h-full border-r">
<div className="flex h-12 items-center justify-between border-b px-4"> <div className="flex h-12 items-center justify-between border-b px-4">
<h1 className="text-sm font-semibold">Agents</h1> <h1 className="text-sm font-semibold">Agents</h1>
<Button <div className="flex items-center gap-1">
variant="ghost" {archivedCount > 0 && (
size="icon-xs" <Button
onClick={() => setShowCreate(true)} variant={showArchived ? "secondary" : "ghost"}
> size="icon-xs"
<Plus className="h-4 w-4 text-muted-foreground" /> onClick={() => setShowArchived(!showArchived)}
</Button> title={showArchived ? "Show active agents" : "Show archived agents"}
>
<Archive className="h-4 w-4 text-muted-foreground" />
</Button>
)}
<Button
variant="ghost"
size="icon-xs"
onClick={() => setShowCreate(true)}
>
<Plus className="h-4 w-4 text-muted-foreground" />
</Button>
</div>
</div> </div>
{agents.length === 0 ? ( {filteredAgents.length === 0 ? (
<div className="flex flex-col items-center justify-center px-4 py-12"> <div className="flex flex-col items-center justify-center px-4 py-12">
<Bot className="h-8 w-8 text-muted-foreground/40" /> <Bot className="h-8 w-8 text-muted-foreground/40" />
<p className="mt-3 text-sm text-muted-foreground">No agents yet</p> <p className="mt-3 text-sm text-muted-foreground">
<Button {showArchived ? "No archived agents" : archivedCount > 0 ? "No active agents" : "No agents yet"}
onClick={() => setShowCreate(true)} </p>
size="xs" {!showArchived && (
className="mt-3" <Button
> onClick={() => setShowCreate(true)}
<Plus className="h-3 w-3" /> size="xs"
Create Agent className="mt-3"
</Button> >
<Plus className="h-3 w-3" />
Create Agent
</Button>
)}
</div> </div>
) : ( ) : (
<div className="divide-y"> <div className="divide-y">
{agents.map((agent) => ( {filteredAgents.map((agent) => (
<AgentListItem <AgentListItem
key={agent.id} key={agent.id}
agent={agent} agent={agent}