From 2f684002b8c3fc57f5d0b3257e807c1915c27de9 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Mon, 2 Mar 2026 14:43:45 -0500 Subject: [PATCH] fix(site): stay on archived chat instead of redirecting (#22505) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When archiving a chat, the frontend no longer navigates away to a different chat. Instead it stays on the current chat and shows an archived state. ## Changes **AgentsPage.tsx** — Removed the redirect logic from `requestArchiveAgent`. After a successful archive, invalidates the individual chat query so the detail view picks up the `archived` flag immediately. **AgentDetail.tsx** — Detects `chatRecord.archived` and: - Disables the chat input - Shows a banner: "This agent has been archived and is read-only." - Passes `isArchived` to the top bar - Guards `handleArchiveAgentAction` against double-archiving **AgentDetail/TopBar.tsx** — When `isArchived`: - Shows an "Archived" badge next to the chat title - Hides the "Archive Agent" dropdown menu item **AgentDetail/TopBar.stories.tsx** — Added an `Archived` story variant. --- site/src/pages/AgentsPage/AgentDetail.tsx | 13 +++++++++-- .../AgentsPage/AgentDetail/TopBar.stories.tsx | 6 +++++ .../pages/AgentsPage/AgentDetail/TopBar.tsx | 23 +++++++++++++------ site/src/pages/AgentsPage/AgentsPage.tsx | 16 ++++--------- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/site/src/pages/AgentsPage/AgentDetail.tsx b/site/src/pages/AgentsPage/AgentDetail.tsx index 5d302d093d..26e605c980 100644 --- a/site/src/pages/AgentsPage/AgentDetail.tsx +++ b/site/src/pages/AgentsPage/AgentDetail.tsx @@ -15,6 +15,7 @@ import { workspaceById } from "api/queries/workspaces"; import type * as TypesGen from "api/typesGenerated"; import type { ModelSelectorOption } from "components/ai-elements"; import { Skeleton } from "components/Skeleton/Skeleton"; +import { ArchiveIcon } from "lucide-react"; import { getVSCodeHref, SESSION_TOKEN_PLACEHOLDER } from "modules/apps/apps"; import { type FC, @@ -514,6 +515,7 @@ const AgentDetail: FC = () => { const workspaceAgent = getWorkspaceAgent(workspace, undefined); const chatData = chatQuery.data; const chatRecord = chatData?.chat; + const isArchived = chatRecord?.archived ?? false; const chatMessages = chatData?.messages; const chatQueuedMessages = chatData?.queued_messages; const chatLastModelConfigID = chatRecord?.last_model_config_id; @@ -637,7 +639,7 @@ const AgentDetail: FC = () => { sendMutation.isPending || editMutation.isPending || interruptMutation.isPending; - const isInputDisabled = !hasModelOptions; + const isInputDisabled = !hasModelOptions || isArchived; const handleSend = async (message: string, editedMessageID?: number) => { if ( @@ -853,7 +855,7 @@ const AgentDetail: FC = () => { }; const handleArchiveAgentAction = () => { - if (!agentId) { + if (!agentId || isArchived) { return; } requestArchiveAgent(agentId); @@ -983,9 +985,16 @@ const AgentDetail: FC = () => { onViewWorkspace: handleViewWorkspace, }} onArchiveAgent={handleArchiveAgentAction} + isArchived={isArchived} isSidebarCollapsed={isSidebarCollapsed} onToggleSidebarCollapsed={onToggleSidebarCollapsed} /> + {isArchived && ( +
+ + This agent has been archived and is read-only. +
+ )}
void; + isArchived?: boolean; isSidebarCollapsed: boolean; onToggleSidebarCollapsed: () => void; }; @@ -92,6 +93,7 @@ export const AgentDetailTopBar: FC = ({ diff, workspace, onArchiveAgent, + isArchived, isSidebarCollapsed, onToggleSidebarCollapsed, }) => { @@ -143,6 +145,11 @@ export const AgentDetailTopBar: FC = ({ {chatTitle} + {isArchived && ( + + Archived + + )}
)} @@ -192,13 +199,15 @@ export const AgentDetailTopBar: FC = ({ View Workspace - - - Archive Agent - + {!isArchived && ( + + + Archive Agent + + )} diff --git a/site/src/pages/AgentsPage/AgentsPage.tsx b/site/src/pages/AgentsPage/AgentsPage.tsx index 9945324817..c801a00529 100644 --- a/site/src/pages/AgentsPage/AgentsPage.tsx +++ b/site/src/pages/AgentsPage/AgentsPage.tsx @@ -221,29 +221,21 @@ const AgentsPage: FC = () => { } setArchivingChatId(chatId); - const nextChatId = ( - queryClient.getQueryData(chats().queryKey) as - | TypesGen.Chat[] - | undefined - )?.find((chat) => chat.id !== chatId)?.id; try { await archiveMutation.mutateAsync(chatId); clearChatErrorReason(chatId); + // Invalidate the individual chat query so the detail view + // picks up the archived flag without a redirect. + await queryClient.invalidateQueries({ queryKey: chatKey(chatId) }); toast.success("Agent archived."); - - if (chatId === agentId) { - navigate(nextChatId ? `/agents/${nextChatId}` : "/agents", { - replace: true, - }); - } } catch (error) { toast.error(getErrorMessage(error, "Failed to archive agent.")); } finally { setArchivingChatId(null); } }, - [archiveMutation, queryClient, agentId, navigate, clearChatErrorReason], + [archiveMutation, queryClient, clearChatErrorReason], ); const handleToggleSidebarCollapsed = useCallback( () => setIsSidebarCollapsed((prev) => !prev),