diff --git a/site/src/components/Alert/Alert.stories.tsx b/site/src/components/Alert/Alert.stories.tsx index fb605f44d3..76606a83b4 100644 --- a/site/src/components/Alert/Alert.stories.tsx +++ b/site/src/components/Alert/Alert.stories.tsx @@ -11,7 +11,7 @@ export default meta; type Story = StoryObj; const ExampleAction = ( - ); diff --git a/site/src/components/Alert/Alert.tsx b/site/src/components/Alert/Alert.tsx index d28f755765..70d31f17e6 100644 --- a/site/src/components/Alert/Alert.tsx +++ b/site/src/components/Alert/Alert.tsx @@ -96,31 +96,37 @@ export const Alert: FC = ({ className={cn(alertVariants({ severity, prominent }), className)} {...props} > -
+
-
{children}
-
-
- {actions} - - {dismissible && ( - - )} +
+
{children}
+ {actions && ( +
{actions}
+ )} +
+ {dismissible && ( + + )}
); }; @@ -139,5 +145,5 @@ export const AlertTitle: React.FC> = ({ className, ...props }) => { - return

; + return

; }; diff --git a/site/src/components/Alert/ErrorAlert.stories.tsx b/site/src/components/Alert/ErrorAlert.stories.tsx index 8a2ea13ecc..44b73cb77d 100644 --- a/site/src/components/Alert/ErrorAlert.stories.tsx +++ b/site/src/components/Alert/ErrorAlert.stories.tsx @@ -21,7 +21,7 @@ export default meta; type Story = StoryObj; const ExampleAction = ( - ); diff --git a/site/src/modules/terminal/WorkspaceTerminalAlerts.tsx b/site/src/modules/terminal/WorkspaceTerminalAlerts.tsx index 5adec2efbd..9f0f89d394 100644 --- a/site/src/modules/terminal/WorkspaceTerminalAlerts.tsx +++ b/site/src/modules/terminal/WorkspaceTerminalAlerts.tsx @@ -75,6 +75,7 @@ const ErrorScriptAlert: FC = () => { )} target="_blank" rel="noreferrer" + className="mx-0" > startup script has exited with an error @@ -164,7 +165,7 @@ const TerminalAlert: FC = (props) => { div]:items-center", + "rounded-none border-0 border-b border-l-[3px] border-b-border-default bg-surface-primary mb-px", severityBorderColors[severity], )} /> @@ -192,7 +193,6 @@ const RefreshSessionButton: FC = () => { } > - {formatUsageLimitMessage(createError.response.data)} + + {formatUsageLimitMessage(createError.response.data)} + ) : ( diff --git a/site/src/pages/AgentsPage/components/ChatAccessDeniedAlert.tsx b/site/src/pages/AgentsPage/components/ChatAccessDeniedAlert.tsx index a12c204d9f..81e2d6fd44 100644 --- a/site/src/pages/AgentsPage/components/ChatAccessDeniedAlert.tsx +++ b/site/src/pages/AgentsPage/components/ChatAccessDeniedAlert.tsx @@ -1,5 +1,5 @@ import type { FC } from "react"; -import { Alert } from "#/components/Alert/Alert"; +import { Alert, AlertDescription, AlertTitle } from "#/components/Alert/Alert"; import { Button } from "#/components/Button/Button"; import { Link } from "#/components/Link/Link"; import { docs } from "#/utils/docs"; @@ -12,28 +12,21 @@ export const ChatAccessDeniedAlert: FC = () => { return ( - - - View Docs - - + } > -

Permission required

-

+ Permission required + You don't have permission to use Coder Agents. Contact your Coder administrator for access. Refresh this page after access has been - granted. -

+ granted.{" "} + + View Docs + +
); }; diff --git a/site/src/pages/AgentsPage/components/ChatConversation/ChatStatusCallout.tsx b/site/src/pages/AgentsPage/components/ChatConversation/ChatStatusCallout.tsx index d1648a9d77..0e5edeb1fc 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/ChatStatusCallout.tsx +++ b/site/src/pages/AgentsPage/components/ChatConversation/ChatStatusCallout.tsx @@ -1,10 +1,8 @@ -import { ExternalLinkIcon } from "lucide-react"; import { type FC, useEffect, useState } from "react"; import { Alert, AlertDescription, AlertTitle } from "#/components/Alert/Alert"; -import { Button } from "#/components/Button/Button"; -import { Pill } from "#/components/Pill/Pill"; +import { Link } from "#/components/Link/Link"; import { Response, Shimmer } from "../ChatElements"; -import { getKindLabel, getProviderStatusURL } from "./chatStatusHelpers"; +import { getProviderStatusURL } from "./chatStatusHelpers"; import type { LiveStatusModel } from "./liveStatusModel"; const RESPONSE_STARTUP_GRACE_MS = 15_000; @@ -116,76 +114,58 @@ const StatusCountdown: FC<{ const StatusAlert: FC<{ status: RetryOrFailedStatus }> = ({ status }) => { const statusURL = getProviderStatusURL(status.kind, status.provider); - const pillType = - status.phase === "failed" - ? "error" - : status.kind === "generic" - ? "inactive" - : "warning"; const severity = status.phase === "failed" ? "error" : status.kind === "generic" ? "info" : "warning"; - const hasMetadata = - status.phase === "retrying" || - (status.phase === "failed" && status.statusCode !== undefined); + const metadataItems: React.ReactNode[] = []; + if (status.phase === "retrying" && status.retryingAt) { + metadataItems.push( + , + ); + } + if (status.phase === "retrying") { + metadataItems.push(Attempt {status.attempt}); + } + if (status.phase === "failed" && status.statusCode !== undefined) { + metadataItems.push(HTTP {status.statusCode}); + } return ( - - Status - - - - ) + metadataItems.length > 0 ? ( +
+ {metadataItems} +
+ ) : undefined } > -
-
- {status.title} - - {getKindLabel(status.kind)} - -
- {status.message} - {hasMetadata && ( -
- {status.phase === "retrying" && status.retryingAt && ( - - )} - {status.phase === "retrying" && ( - Attempt {status.attempt} - )} - - {status.phase === "failed" && status.statusCode !== undefined && ( - HTTP {status.statusCode} - )} -
+ {status.title} + + {status.message}{" "} + {statusURL && ( + + Status + )} -
+
); }; const ReconnectingAlert: FC<{ status: ReconnectingStatus }> = ({ status }) => { return ( - -
- {status.title} - {status.message} + = ({ status }) => { /> Attempt {status.attempt}
- + } + > + {status.title} + {status.message}
); }; diff --git a/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.stories.tsx b/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.stories.tsx index db2c943ed5..0907f16ba7 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.stories.tsx +++ b/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.stories.tsx @@ -92,7 +92,6 @@ export const TerminalOverloadedError: Story = { expect( canvas.getByRole("heading", { name: /service overloaded/i }), ).toBeVisible(); - expect(canvas.getByText("Overloaded")).toBeVisible(); expect( canvas.getByText(/anthropic is currently overloaded./i), ).toBeVisible(); @@ -122,7 +121,6 @@ export const TerminalStartupTimeoutError: Story = { expect( canvas.getByRole("heading", { name: /startup timed out/i }), ).toBeVisible(); - expect(canvas.getByText("Startup timeout")).toBeVisible(); expect( canvas.getByText(/anthropic did not start responding in time./i), ).toBeVisible(); diff --git a/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.tsx b/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.tsx index af100016da..b29a4a5f6c 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.tsx +++ b/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.tsx @@ -1,7 +1,7 @@ import { Link } from "react-router"; import type { UrlTransform } from "streamdown"; import type * as TypesGen from "#/api/typesGenerated"; -import { Alert } from "#/components/Alert/Alert"; +import { Alert, AlertDescription } from "#/components/Alert/Alert"; import { Button } from "#/components/Button/Button"; import type { ChatDetailError } from "../../utils/usageLimitMessage"; import { ChatStatusCallout } from "./ChatStatusCallout"; @@ -92,14 +92,13 @@ export const LiveStreamTailContent = ({ {usageLimitStatus ? ( + } > - {usageLimitStatus.message} + {usageLimitStatus.message} ) : terminalStatus ? ( diff --git a/site/src/pages/AgentsPage/components/ChatConversation/StreamingOutput.stories.tsx b/site/src/pages/AgentsPage/components/ChatConversation/StreamingOutput.stories.tsx index 2879be7a79..62d6099565 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/StreamingOutput.stories.tsx +++ b/site/src/pages/AgentsPage/components/ChatConversation/StreamingOutput.stories.tsx @@ -95,7 +95,6 @@ export const RetryWithVisibleReason: Story = { expect( canvas.getByText(/anthropic returned an unexpected error/i), ).toBeVisible(); - expect(canvas.getByText("Unexpected error")).toBeVisible(); expect(canvas.getByText(/attempt 1/i)).toBeVisible(); expect(canvas.queryByText(/please try again/i)).not.toBeInTheDocument(); expect(canvas.queryByText(/provider anthropic/i)).not.toBeInTheDocument(); @@ -125,7 +124,6 @@ export const RetryRateLimited: Story = { expect( canvas.getByText(/anthropic is rate limiting requests/i), ).toBeVisible(); - expect(canvas.getByText("Rate limit")).toBeVisible(); await waitFor(() => { expect(canvasElement.textContent).toMatch(/retrying in \d+s/i); }); @@ -160,7 +158,6 @@ export const RetryInvalidTimestamp: Story = { expect( canvas.getByText(/anthropic is rate limiting requests/i), ).toBeVisible(); - expect(canvas.getByText("Rate limit")).toBeVisible(); expect(canvas.getByText(/attempt 3/i)).toBeVisible(); await waitFor(() => { expect(canvas.queryByText(/retrying in nan/i)).not.toBeInTheDocument(); @@ -192,7 +189,6 @@ export const RetryOverloaded: Story = { expect( canvas.getByText(/anthropic is temporarily overloaded/i), ).toBeVisible(); - expect(canvas.getByText("Overloaded")).toBeVisible(); const statusLink = screen.getByRole("link", { name: /status/i }); expect(statusLink).toBeVisible(); expect(statusLink).toHaveAttribute("href", "https://status.anthropic.com"); @@ -221,7 +217,6 @@ export const RetryTimeout: Story = { expect( canvas.getByText(/anthropic is temporarily unavailable/i), ).toBeVisible(); - expect(canvas.getByText("Timeout")).toBeVisible(); expect( canvas.queryByRole("link", { name: /status/i }), ).not.toBeInTheDocument(); @@ -250,7 +245,6 @@ export const RetryStartupTimeout: Story = { expect( canvas.getByText(/anthropic did not start responding in time/i), ).toBeVisible(); - expect(canvas.getByText("Startup timeout")).toBeVisible(); expect(canvas.queryByText(/please try again/i)).not.toBeInTheDocument(); expect(canvas.queryByText(/provider anthropic/i)).not.toBeInTheDocument(); expect( diff --git a/site/src/pages/AgentsPage/components/ChatConversation/chatStatusHelpers.ts b/site/src/pages/AgentsPage/components/ChatConversation/chatStatusHelpers.ts index 36ab6fb534..f174733bb6 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/chatStatusHelpers.ts +++ b/site/src/pages/AgentsPage/components/ChatConversation/chatStatusHelpers.ts @@ -23,19 +23,6 @@ const normalizeProvider = (provider?: string): string | undefined => { } }; -const humanizeKind = (kind: string): string => { - const words = kind - .trim() - .split(/[_\-\s]+/) - .filter(Boolean); - if (words.length === 0) { - return "Unexpected error"; - } - return words - .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) - .join(" "); -}; - export const getErrorTitle = ( kind: ChatProviderFailureKind | (string & {}), mode: "retry" | "error", @@ -58,29 +45,6 @@ export const getErrorTitle = ( } }; -export const getKindLabel = ( - kind: ChatProviderFailureKind | (string & {}), -): string => { - switch (kind) { - case "generic": - return "Unexpected error"; - case "overloaded": - return "Overloaded"; - case "rate_limit": - return "Rate limit"; - case "timeout": - return "Timeout"; - case "startup_timeout": - return "Startup timeout"; - case "auth": - return "Authentication"; - case "config": - return "Configuration"; - default: - return humanizeKind(kind); - } -}; - export const getProviderStatusURL = ( kind: ChatProviderFailureKind | (string & {}), provider?: string, diff --git a/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.tsx b/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.tsx index d9bae7174f..3342483f5b 100644 --- a/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.tsx +++ b/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.tsx @@ -71,7 +71,7 @@ export const NotificationEvents: FC = ({ severity="warning" prominent actions={ - } > - Successfully published {publishedVersion.name}! + + Successfully published {publishedVersion.name}! + )} diff --git a/site/src/pages/WorkspacePage/WorkspaceDeletedBanner.tsx b/site/src/pages/WorkspacePage/WorkspaceDeletedBanner.tsx index 1f93259b81..189fa64e67 100644 --- a/site/src/pages/WorkspacePage/WorkspaceDeletedBanner.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceDeletedBanner.tsx @@ -10,7 +10,7 @@ export const WorkspaceDeletedBanner: FC = ({ handleClick, }) => { const NewWorkspaceButton = ( - );