From 39ceb8cfe36a8b5677d8c315a6326558c0535ce6 Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Mon, 13 Apr 2026 13:03:12 +0100 Subject: [PATCH] fix(site): show "Preparing" in workspace pill during agent startup scripts (#24286) --- site/src/pages/AgentsPage/AgentChatPage.tsx | 5 +- .../AgentsPage/AgentChatPageView.stories.tsx | 74 ++++++++++++++++++- .../pages/AgentsPage/AgentChatPageView.tsx | 17 ++++- 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/site/src/pages/AgentsPage/AgentChatPage.tsx b/site/src/pages/AgentsPage/AgentChatPage.tsx index 2f0c6aa01c..140599324c 100644 --- a/site/src/pages/AgentsPage/AgentChatPage.tsx +++ b/site/src/pages/AgentsPage/AgentChatPage.tsx @@ -470,6 +470,7 @@ type _UncoveredAgentFields = Omit< | "status" | "name" | "expanded_directory" + | "lifecycle_state" // Fields below are intentionally not compared. They change // frequently (stats, metadata) or are objects/arrays that would // require deep comparison, and the UI does not read them. @@ -481,7 +482,6 @@ type _UncoveredAgentFields = Omit< | "disconnected_at" | "started_at" | "ready_at" - | "lifecycle_state" | "resource_id" | "instance_id" | "architecture" @@ -641,7 +641,8 @@ const AgentChatPage: FC = () => { prevAgent?.status === nextAgent?.status && prevAgent?.name === nextAgent?.name && prevAgent?.expanded_directory === - nextAgent?.expanded_directory + nextAgent?.expanded_directory && + prevAgent?.lifecycle_state === nextAgent?.lifecycle_state ) { return prev; } diff --git a/site/src/pages/AgentsPage/AgentChatPageView.stories.tsx b/site/src/pages/AgentsPage/AgentChatPageView.stories.tsx index ced1b0506f..c00958a329 100644 --- a/site/src/pages/AgentsPage/AgentChatPageView.stories.tsx +++ b/site/src/pages/AgentsPage/AgentChatPageView.stories.tsx @@ -5,7 +5,11 @@ import { reactRouterParameters } from "storybook-addon-remix-react-router"; import { API } from "#/api/api"; import type * as TypesGen from "#/api/typesGenerated"; import type { ChatDiffStatus, ChatMessagePart } from "#/api/typesGenerated"; -import { MockUserOwner } from "#/testHelpers/entities"; +import { + MockUserOwner, + MockWorkspace, + MockWorkspaceAgent, +} from "#/testHelpers/entities"; import { withAuthProvider, withDashboardProvider, @@ -373,6 +377,74 @@ export const WithWorkspaceActions: Story = { ), }; +// --------------------------------------------------------------------------- +// Workspace status pill stories +// --------------------------------------------------------------------------- + +export const WorkspaceAgentStarting: Story = { + render: () => ( + + ), +}; + +export const WorkspaceAgentCreated: Story = { + render: () => ( + + ), +}; + +export const WorkspaceAgentReady: Story = { + render: () => ( + + ), +}; + +export const WorkspaceAgentStartError: Story = { + render: () => ( + + ), +}; + +export const WorkspaceAgentStartTimeout: Story = { + render: () => ( + + ), +}; + +export const WorkspaceNoAgent: Story = { + render: () => , +}; + // --------------------------------------------------------------------------- // AgentChatPageLoadingView stories // --------------------------------------------------------------------------- diff --git a/site/src/pages/AgentsPage/AgentChatPageView.tsx b/site/src/pages/AgentsPage/AgentChatPageView.tsx index 2056ba48c0..6655c4d27c 100644 --- a/site/src/pages/AgentsPage/AgentChatPageView.tsx +++ b/site/src/pages/AgentsPage/AgentChatPageView.tsx @@ -278,10 +278,25 @@ export const AgentChatPageView: FC = ({ const attachedWorkspace = (() => { if (!workspace || !workspaceRoute) return undefined; - const { type, text } = getDisplayWorkspaceStatus( + let { type, text } = getDisplayWorkspaceStatus( workspace.latest_build.status, workspace.latest_build.job, ); + const agentPreparing = + workspace.latest_build.status === "running" && + (workspaceAgent?.lifecycle_state === "created" || + workspaceAgent?.lifecycle_state === "starting"); + const agentStartupFailed = + workspace.latest_build.status === "running" && + (workspaceAgent?.lifecycle_state === "start_error" || + workspaceAgent?.lifecycle_state === "start_timeout"); + if (agentPreparing) { + type = "active"; + text = "Preparing"; + } else if (agentStartupFailed) { + type = "warning"; + text = "Startup failed"; + } const effectiveType = workspace.health.healthy ? type : "warning"; const statusLabel = workspace.health.healthy ? `Workspace ${text.toLowerCase()}`