refactor(site/src/pages/AgentsPage): centralize setup notice rendering (#26134)

This commit is contained in:
Danielle Maywood
2026-06-11 12:43:53 +01:00
committed by GitHub
parent f865281177
commit ba51ee8f98
8 changed files with 87 additions and 92 deletions
+3 -27
View File
@@ -63,7 +63,6 @@ import {
} from "./AgentChatPageView";
import type { AgentsOutletContext } from "./AgentsPage";
import type { ChatMessageInputRef } from "./components/AgentChatInput";
import { AgentSetupNotice } from "./components/AgentSetupNotice";
import { normalizeChatErrorPayload } from "./components/ChatConversation/chatError";
import {
getParentChatID,
@@ -1130,31 +1129,6 @@ const AgentChatPage: FC = () => {
hasConfiguredModels,
hasUserFixableModelProviders,
});
const isAdmin = permissions.editDeploymentConfig;
const agentSetupNotice = (() => {
// Admin: show when providers or models are missing
if (
isAdmin &&
providerCount !== undefined &&
modelCount !== undefined &&
(providerCount === 0 || modelCount === 0)
) {
return (
<AgentSetupNotice
isAdmin
providerCount={providerCount}
modelCount={modelCount}
/>
);
}
// Member: show when no models are available
if (!isAdmin && modelCount !== undefined && modelCount === 0) {
return (
<AgentSetupNotice isAdmin={false} providerCount={0} modelCount={0} />
);
}
return undefined;
})();
const isSubmissionPending =
isSendPending || isEditPending || isInterruptPending;
const isChatSettingsPending =
@@ -1626,7 +1600,9 @@ const AgentChatPage: FC = () => {
modelOptions={modelOptions}
modelSelectorPlaceholder={modelSelectorPlaceholder}
modelSelectorHelp={modelSelectorHelp}
agentSetupNotice={agentSetupNotice}
canConfigureAgentSetup={permissions.editDeploymentConfig}
providerCount={providerCount}
modelCount={modelCount}
hasModelOptions={hasModelOptions}
isModelCatalogLoading={isModelCatalogLoading}
planModeEnabled={planModeEnabled}
@@ -25,7 +25,6 @@ import {
AgentChatPageNotFoundView,
AgentChatPageView,
} from "./AgentChatPageView";
import { AgentSetupNotice } from "./components/AgentSetupNotice";
import {
createChatStore,
useChatSelector,
@@ -190,6 +189,9 @@ const StoryAgentChatPageView: FC<StoryProps> = ({ editing, ...overrides }) => {
onMCPSelectionChange: fn(),
onMCPAuthComplete: fn(),
canShareChat: false,
canConfigureAgentSetup: true,
providerCount: 1,
modelCount: 1,
...overrides,
store,
messageCount: overrides.messageCount ?? messageCount,
@@ -528,9 +530,9 @@ export const NoModelOptions: Story = {
export const MissingProviderAndModelSetup: Story = {
render: () => (
<StoryAgentChatPageView
agentSetupNotice={
<AgentSetupNotice isAdmin providerCount={0} modelCount={0} />
}
canConfigureAgentSetup
providerCount={0}
modelCount={0}
hasModelOptions={false}
modelOptions={[]}
isInputDisabled
@@ -563,9 +565,9 @@ export const MissingProviderAndModelSetup: Story = {
export const MissingModelSetup: Story = {
render: () => (
<StoryAgentChatPageView
agentSetupNotice={
<AgentSetupNotice isAdmin providerCount={1} modelCount={0} />
}
canConfigureAgentSetup
providerCount={1}
modelCount={0}
hasModelOptions={false}
modelOptions={[]}
isInputDisabled
@@ -594,9 +596,9 @@ export const MissingModelSetup: Story = {
export const MissingProviderSetup: Story = {
render: () => (
<StoryAgentChatPageView
agentSetupNotice={
<AgentSetupNotice isAdmin providerCount={0} modelCount={1} />
}
canConfigureAgentSetup
providerCount={0}
modelCount={1}
/>
),
play: async ({ canvasElement }) => {
@@ -622,9 +624,9 @@ export const MissingProviderSetup: Story = {
export const MemberNoModelsAvailable: Story = {
render: () => (
<StoryAgentChatPageView
agentSetupNotice={
<AgentSetupNotice isAdmin={false} providerCount={0} modelCount={0} />
}
canConfigureAgentSetup={false}
providerCount={0}
modelCount={0}
hasModelOptions={false}
modelOptions={[]}
isInputDisabled
@@ -128,7 +128,9 @@ interface AgentChatPageViewProps {
modelOptions: readonly ModelSelectorOption[];
modelSelectorPlaceholder: string;
modelSelectorHelp?: ReactNode;
agentSetupNotice?: ReactNode;
canConfigureAgentSetup: boolean;
providerCount?: number;
modelCount?: number;
hasModelOptions: boolean;
isModelCatalogLoading?: boolean;
planModeEnabled?: boolean;
@@ -263,7 +265,9 @@ export const AgentChatPageView: FC<AgentChatPageViewProps> = ({
modelOptions,
modelSelectorPlaceholder,
modelSelectorHelp,
agentSetupNotice,
canConfigureAgentSetup,
providerCount,
modelCount,
hasModelOptions,
isModelCatalogLoading = false,
planModeEnabled,
@@ -748,12 +752,14 @@ export const AgentChatPageView: FC<AgentChatPageViewProps> = ({
isSendPending={isSubmissionPending}
isInterruptPending={isInterruptPending}
hasModelOptions={hasModelOptions}
canConfigureAgentSetup={canConfigureAgentSetup}
providerCount={providerCount}
modelCount={modelCount}
selectedModel={effectiveSelectedModel}
onModelChange={setSelectedModel}
modelOptions={modelOptions}
modelSelectorPlaceholder={modelSelectorPlaceholder}
modelSelectorHelp={modelSelectorHelp}
agentSetupNotice={agentSetupNotice}
planModeEnabled={planModeEnabled}
onPlanModeToggle={onPlanModeToggle}
isModelCatalogLoading={isModelCatalogLoading}
@@ -911,6 +917,7 @@ export const AgentChatPageLoadingView: FC<AgentChatPageLoadingViewProps> = ({
onPlanModeToggle={onPlanModeToggle}
isModelCatalogLoading={isModelCatalogLoading}
hasModelOptions={hasModelOptions}
canConfigureAgentSetup={false}
/>
</div>{" "}
</div>
+3 -25
View File
@@ -21,7 +21,6 @@ import {
type CreateChatOptions,
} from "./components/AgentCreateForm";
import { AgentPageHeader } from "./components/AgentPageHeader";
import { AgentSetupNotice } from "./components/AgentSetupNotice";
import { ChimeButton } from "./components/ChimeButton";
import { WebPushButton } from "./components/WebPushButton";
import { getAgentChatSendShortcut } from "./utils/agentChatSendShortcut";
@@ -73,29 +72,6 @@ const AgentCreatePage: FC = () => {
chatModelConfigsQuery.isSuccess && chatModelsQuery.isSuccess
? catalogModelOptions.length
: undefined;
const isAdmin = permissions.editDeploymentConfig;
const agentSetupNotice = (() => {
if (
isAdmin &&
providerCount !== undefined &&
modelCount !== undefined &&
(providerCount === 0 || modelCount === 0)
) {
return (
<AgentSetupNotice
isAdmin
providerCount={providerCount}
modelCount={modelCount}
/>
);
}
if (!isAdmin && modelCount !== undefined && modelCount === 0) {
return (
<AgentSetupNotice isAdmin={false} providerCount={0} modelCount={0} />
);
}
return undefined;
})();
const handleCreateChat = async ({
message,
@@ -181,7 +157,9 @@ const AgentCreatePage: FC = () => {
canCreateChat={permissions.createChat}
modelCatalog={chatModelsQuery.data}
modelOptions={catalogModelOptions}
agentSetupNotice={agentSetupNotice}
canConfigureAgentSetup={permissions.editDeploymentConfig}
providerCount={providerCount}
modelCount={modelCount}
modelConfigs={chatModelConfigsQuery.data ?? []}
isModelCatalogLoading={chatModelsQuery.isLoading}
isModelConfigsLoading={chatModelConfigsQuery.isLoading}
@@ -67,6 +67,7 @@ import {
isChatAttachmentFile,
} from "../utils/chatAttachments";
import { formatProviderLabel } from "../utils/modelOptions";
import { AgentSetupNotice } from "./AgentSetupNotice";
import {
AttachmentPreview,
isUploadInProgress,
@@ -183,7 +184,9 @@ interface AgentChatInputProps {
sshCommand?: string;
attachedWorkspace?: AttachedWorkspaceInfo;
folder?: string;
agentSetupNotice?: React.ReactNode;
canConfigureAgentSetup: boolean;
providerCount?: number;
modelCount?: number;
}
export interface AttachedWorkspaceInfo {
@@ -381,9 +384,16 @@ export const AgentChatInput: FC<AgentChatInputProps> = ({
sshCommand,
attachedWorkspace,
folder,
agentSetupNotice,
canConfigureAgentSetup,
providerCount,
modelCount,
}) => {
const [chatFullWidth] = useChatFullWidth();
const showAgentSetupNotice = canConfigureAgentSetup
? providerCount !== undefined &&
modelCount !== undefined &&
(providerCount === 0 || modelCount === 0)
: modelCount !== undefined && modelCount === 0;
const internalRef = useRef<ChatMessageInputRef>(null);
const [previewImage, setPreviewImage] = useState<string | null>(null);
const [previewText, setPreviewText] = useState<string | null>(null);
@@ -1044,15 +1054,31 @@ export const AgentChatInput: FC<AgentChatInputProps> = ({
className="mb-2"
/>
)}
{agentSetupNotice && (
<div className="relative z-0 mb-[-2.5rem]">{agentSetupNotice}</div>
{showAgentSetupNotice && (
<div className="relative z-0 mb-[-2.5rem]">
{canConfigureAgentSetup &&
providerCount !== undefined &&
modelCount !== undefined ? (
<AgentSetupNotice
isAdmin
providerCount={providerCount}
modelCount={modelCount}
/>
) : (
<AgentSetupNotice
isAdmin={false}
providerCount={0}
modelCount={0}
/>
)}
</div>
)}
<div
ref={setComposerElement}
data-testid="chat-composer"
className={cn(
"relative z-10 rounded-2xl border border-border-default/80 bg-surface-secondary sm:bg-surface-secondary/45 p-1 shadow-sm has-[textarea:focus]:ring-2 has-[textarea:focus]:ring-content-link/40",
agentSetupNotice && "sm:bg-surface-secondary",
showAgentSetupNotice && "sm:bg-surface-secondary",
isDragging && "ring-2 ring-content-link/40",
isEditingHistoryMessage &&
"shadow-[0_0_0_2px_hsla(var(--border-warning),0.6)]",
@@ -1177,7 +1203,9 @@ export const AgentChatInput: FC<AgentChatInputProps> = ({
size="icon"
className="size-7 shrink-0 rounded-full [&>svg]:!size-icon-sm [&>svg]:p-0"
disabled={
isDisabled && !agentSetupNotice && !canUseWorkspacePicker
isDisabled &&
!showAgentSetupNotice &&
!canUseWorkspacePicker
}
aria-label="More options"
>
@@ -18,7 +18,6 @@ import {
} from "#/testHelpers/entities";
import { withDashboardProvider } from "#/testHelpers/storybook";
import { AgentCreateForm } from "./AgentCreateForm";
import { AgentSetupNotice } from "./AgentSetupNotice";
// Query key used by permittedOrganizations() in the form.
const permittedOrgsKey = [
@@ -471,9 +470,9 @@ export const NoModelsConfigured: Story = {
export const MissingProviderAndModelSetup: Story = {
args: {
...defaultArgs,
agentSetupNotice: (
<AgentSetupNotice isAdmin providerCount={0} modelCount={0} />
),
canConfigureAgentSetup: true,
providerCount: 0,
modelCount: 0,
modelCatalog: { providers: [] },
modelOptions: [],
isModelCatalogLoading: false,
@@ -1,11 +1,4 @@
import {
type FC,
type ReactNode,
useEffect,
useEffectEvent,
useRef,
useState,
} from "react";
import { type FC, useEffect, useEffectEvent, useRef, useState } from "react";
import { useQuery } from "react-query";
import { Link } from "react-router";
import { toast } from "sonner";
@@ -132,7 +125,9 @@ interface AgentCreateFormProps {
canCreateChat: boolean;
modelCatalog: TypesGen.ChatModelsResponse | null | undefined;
modelOptions: readonly ChatModelOption[];
agentSetupNotice?: ReactNode;
canConfigureAgentSetup: boolean;
providerCount?: number;
modelCount?: number;
isModelCatalogLoading: boolean;
modelConfigs: readonly TypesGen.ChatModelConfig[];
isModelConfigsLoading: boolean;
@@ -154,7 +149,9 @@ export const AgentCreateForm: FC<AgentCreateFormProps> = ({
canCreateChat,
modelCatalog,
modelOptions,
agentSetupNotice,
canConfigureAgentSetup,
providerCount,
modelCount,
modelConfigs,
isModelCatalogLoading,
isModelConfigsLoading,
@@ -548,7 +545,9 @@ export const AgentCreateForm: FC<AgentCreateFormProps> = ({
selectedWorkspaceId={effectiveWorkspaceId}
onWorkspaceChange={handleWorkspaceChange}
isWorkspaceLoading={isWorkspacesLoading}
agentSetupNotice={agentSetupNotice}
canConfigureAgentSetup={canConfigureAgentSetup}
providerCount={providerCount}
modelCount={modelCount}
/>
{modelSelectorHelp ? (
<div className="px-3 pt-1 text-2xs text-content-secondary">
@@ -169,7 +169,9 @@ interface ChatPageInputProps {
modelOptions: readonly ModelSelectorOption[];
modelSelectorPlaceholder: string;
modelSelectorHelp?: ReactNode;
agentSetupNotice?: ReactNode;
canConfigureAgentSetup: boolean;
providerCount?: number;
modelCount?: number;
planModeEnabled?: boolean;
onPlanModeToggle?: (enabled: boolean) => void;
isModelCatalogLoading?: boolean;
@@ -234,7 +236,9 @@ export const ChatPageInput: FC<ChatPageInputProps> = ({
modelOptions,
modelSelectorPlaceholder,
modelSelectorHelp,
agentSetupNotice,
canConfigureAgentSetup,
providerCount,
modelCount,
planModeEnabled,
onPlanModeToggle,
isModelCatalogLoading = false,
@@ -490,7 +494,9 @@ export const ChatPageInput: FC<ChatPageInputProps> = ({
sshCommand={sshCommand}
attachedWorkspace={attachedWorkspace}
folder={folder}
agentSetupNotice={agentSetupNotice}
canConfigureAgentSetup={canConfigureAgentSetup}
providerCount={providerCount}
modelCount={modelCount}
/>
);