diff --git a/site/src/pages/AgentsPage/AgentCreatePage.tsx b/site/src/pages/AgentsPage/AgentCreatePage.tsx index 9d3e6879d2..ed9e452840 100644 --- a/site/src/pages/AgentsPage/AgentCreatePage.tsx +++ b/site/src/pages/AgentsPage/AgentCreatePage.tsx @@ -89,7 +89,6 @@ const AgentCreatePage: FC = () => { modelConfigs={chatModelConfigsQuery.data ?? []} isModelCatalogLoading={chatModelsQuery.isLoading} isModelConfigsLoading={chatModelConfigsQuery.isLoading} - modelCatalogError={chatModelsQuery.error} mcpServers={mcpServersQuery.data ?? []} onMCPAuthComplete={() => void mcpServersQuery.refetch()} /> diff --git a/site/src/pages/AgentsPage/AgentDetail.tsx b/site/src/pages/AgentsPage/AgentDetail.tsx index 3af474aaff..c05b2423b7 100644 --- a/site/src/pages/AgentsPage/AgentDetail.tsx +++ b/site/src/pages/AgentsPage/AgentDetail.tsx @@ -60,7 +60,6 @@ import { useGitWatcher } from "./hooks/useGitWatcher"; import { buildModelConfigIDByModelID, buildModelIDByConfigID, - getModelCatalogStatusMessage, getModelOptionsFromCatalog, getModelSelectorPlaceholder, hasConfiguredModelsInCatalog, @@ -345,7 +344,6 @@ const AgentDetail: FC = () => { const modelConfigs = chatModelConfigsQuery.data ?? []; const modelCatalog = chatModelsQuery.data; const isModelCatalogLoading = chatModelsQuery.isLoading; - const modelCatalogError = chatModelsQuery.error; // Subscribe to live workspace updates so that agent status changes // (e.g. connected/disconnected) are reflected without a page refresh. @@ -542,17 +540,6 @@ const AgentDetail: FC = () => { isModelCatalogLoading, hasConfiguredModels, ); - const modelCatalogStatusMessage = getModelCatalogStatusMessage( - modelCatalog, - modelOptions, - isModelCatalogLoading, - Boolean(modelCatalogError), - ); - const inputStatusText = hasModelOptions - ? null - : hasConfiguredModels - ? "Models are configured but unavailable. Ask an admin." - : "No models configured. Ask an admin."; const isSubmissionPending = sendMutation.isPending || editMutation.isPending || @@ -858,8 +845,7 @@ const AgentDetail: FC = () => { modelOptions={modelOptions} modelSelectorPlaceholder={modelSelectorPlaceholder} hasModelOptions={hasModelOptions} - inputStatusText={inputStatusText} - modelCatalogStatusMessage={modelCatalogStatusMessage} + isModelCatalogLoading={isModelCatalogLoading} isSidebarCollapsed={isSidebarCollapsed} onToggleSidebarCollapsed={onToggleSidebarCollapsed} showRightPanel={showSidebarPanel} @@ -894,8 +880,7 @@ const AgentDetail: FC = () => { modelOptions={modelOptions} modelSelectorPlaceholder={modelSelectorPlaceholder} hasModelOptions={hasModelOptions} - inputStatusText={inputStatusText} - modelCatalogStatusMessage={modelCatalogStatusMessage} + isModelCatalogLoading={isModelCatalogLoading} compressionThreshold={compressionThreshold} isInputDisabled={isInputDisabled} isSubmissionPending={isSubmissionPending} diff --git a/site/src/pages/AgentsPage/components/AgentChatInput.stories.tsx b/site/src/pages/AgentsPage/components/AgentChatInput.stories.tsx index 2b5e169569..b459bfbaa4 100644 --- a/site/src/pages/AgentsPage/components/AgentChatInput.stories.tsx +++ b/site/src/pages/AgentsPage/components/AgentChatInput.stories.tsx @@ -28,8 +28,6 @@ const meta: Meta = { modelOptions: [...defaultModelOptions], modelSelectorPlaceholder: "Select model", hasModelOptions: true, - inputStatusText: null, - modelCatalogStatusMessage: null, }, }; diff --git a/site/src/pages/AgentsPage/components/AgentChatInput.tsx b/site/src/pages/AgentsPage/components/AgentChatInput.tsx index 45425ded77..87169e400b 100644 --- a/site/src/pages/AgentsPage/components/AgentChatInput.tsx +++ b/site/src/pages/AgentsPage/components/AgentChatInput.tsx @@ -48,6 +48,7 @@ import { PopoverTrigger, } from "#/components/Popover/Popover"; import { Separator } from "#/components/Separator/Separator"; +import { Skeleton } from "#/components/Skeleton/Skeleton"; import { Spinner } from "#/components/Spinner/Spinner"; import { Switch } from "#/components/Switch/Switch"; import { @@ -104,9 +105,7 @@ interface AgentChatInputProps { modelOptions: readonly ModelSelectorOption[]; modelSelectorPlaceholder: string; hasModelOptions: boolean; - // Status messages. - inputStatusText: string | null; - modelCatalogStatusMessage: string | null; + isModelCatalogLoading?: boolean; // Streaming controls (optional, for the detail page). isStreaming?: boolean; onInterrupt?: () => void; @@ -468,8 +467,7 @@ export const AgentChatInput: FC = ({ modelOptions, modelSelectorPlaceholder, hasModelOptions, - inputStatusText, - modelCatalogStatusMessage, + isModelCatalogLoading = false, isStreaming = false, onInterrupt, isInterruptPending = false, @@ -1027,16 +1025,20 @@ export const AgentChatInput: FC = ({ )} - + {isModelCatalogLoading ? ( + + ) : ( + + )} {selectedWorkspace && onWorkspaceChange && ( @@ -1081,11 +1083,6 @@ export const AgentChatInput: FC = ({ ); })} - {inputStatusText && ( - - {inputStatusText} - - )}
{speech.isSupported && !isStreaming && ( @@ -1158,16 +1155,6 @@ export const AgentChatInput: FC = ({ )}
- {inputStatusText && ( -
- {inputStatusText} -
- )} - {modelCatalogStatusMessage && ( -
- {modelCatalogStatusMessage} -
- )} ); diff --git a/site/src/pages/AgentsPage/components/AgentCreateForm.stories.tsx b/site/src/pages/AgentsPage/components/AgentCreateForm.stories.tsx index 6c3d566489..9683186f3d 100644 --- a/site/src/pages/AgentsPage/components/AgentCreateForm.stories.tsx +++ b/site/src/pages/AgentsPage/components/AgentCreateForm.stories.tsx @@ -27,7 +27,6 @@ const meta: Meta = { isModelCatalogLoading: false, modelConfigs: [], isModelConfigsLoading: false, - modelCatalogError: undefined, }, beforeEach: () => { localStorage.clear(); @@ -170,6 +169,26 @@ export const SelectWorkspaceViaSearch: Story = { }, }; +export const LoadingModelCatalog: Story = { + args: { + ...defaultArgs, + modelCatalog: null, + modelOptions: [], + isModelCatalogLoading: true, + isModelConfigsLoading: true, + }, +}; + +export const NoModelsConfigured: Story = { + args: { + ...defaultArgs, + modelCatalog: { providers: [] }, + modelOptions: [], + isModelCatalogLoading: false, + isModelConfigsLoading: false, + }, +}; + export const UsageLimitExceeded: Story = { args: { ...defaultArgs, diff --git a/site/src/pages/AgentsPage/components/AgentCreateForm.tsx b/site/src/pages/AgentsPage/components/AgentCreateForm.tsx index 0def0121b6..2b1f71e3ef 100644 --- a/site/src/pages/AgentsPage/components/AgentCreateForm.tsx +++ b/site/src/pages/AgentsPage/components/AgentCreateForm.tsx @@ -12,7 +12,6 @@ import { Button } from "#/components/Button/Button"; import { useDashboard } from "#/modules/dashboard/useDashboard"; import { useFileAttachments } from "../hooks/useFileAttachments"; import { - getModelCatalogStatusMessage, getModelSelectorPlaceholder, getNormalizedModelRef, hasConfiguredModelsInCatalog, @@ -103,7 +102,6 @@ interface AgentCreateFormProps { isModelCatalogLoading: boolean; modelConfigs: readonly TypesGen.ChatModelConfig[]; isModelConfigsLoading: boolean; - modelCatalogError: unknown; mcpServers?: readonly TypesGen.MCPServerConfig[]; onMCPAuthComplete?: (serverId: string) => void; } @@ -117,7 +115,6 @@ export const AgentCreateForm: FC = ({ modelConfigs, isModelCatalogLoading, isModelConfigsLoading, - modelCatalogError, mcpServers, onMCPAuthComplete, }) => { @@ -190,18 +187,6 @@ export const AgentCreateForm: FC = ({ isModelCatalogLoading, hasConfiguredModels, ); - const modelCatalogStatusMessage = getModelCatalogStatusMessage( - modelCatalog, - modelOptions, - isModelCatalogLoading, - Boolean(modelCatalogError), - ); - const inputStatusText = hasModelOptions - ? null - : hasConfiguredModels - ? "Models are configured but unavailable. Ask an admin." - : "No models configured. Ask an admin."; - useEffect(() => { if (!initialLastModelConfigID) { return; @@ -350,9 +335,8 @@ export const AgentCreateForm: FC = ({ onModelChange={handleModelChange} modelOptions={modelOptions} modelSelectorPlaceholder={modelSelectorPlaceholder} + isModelCatalogLoading={isModelCatalogLoading} hasModelOptions={hasModelOptions} - inputStatusText={inputStatusText} - modelCatalogStatusMessage={modelCatalogStatusMessage} attachments={attachments} onAttach={handleAttach} onRemoveAttachment={handleRemoveAttachment} diff --git a/site/src/pages/AgentsPage/components/AgentDetailContent.tsx b/site/src/pages/AgentsPage/components/AgentDetailContent.tsx index 9b3ad2ca30..51fa99da89 100644 --- a/site/src/pages/AgentsPage/components/AgentDetailContent.tsx +++ b/site/src/pages/AgentsPage/components/AgentDetailContent.tsx @@ -200,8 +200,7 @@ interface AgentDetailInputProps { onModelChange: (modelID: string) => void; modelOptions: readonly ModelSelectorOption[]; modelSelectorPlaceholder: string; - inputStatusText: string | null; - modelCatalogStatusMessage: string | null; + isModelCatalogLoading?: boolean; // Controlled input value and editing state, owned by the // conversation component. inputRef?: React.Ref; @@ -240,8 +239,7 @@ export const AgentDetailInput: FC = ({ onModelChange, modelOptions, modelSelectorPlaceholder, - inputStatusText, - modelCatalogStatusMessage, + isModelCatalogLoading = false, inputRef, initialValue, onContentChange, @@ -392,8 +390,7 @@ export const AgentDetailInput: FC = ({ onModelChange={onModelChange} modelOptions={modelOptions} modelSelectorPlaceholder={modelSelectorPlaceholder} - inputStatusText={inputStatusText} - modelCatalogStatusMessage={modelCatalogStatusMessage} + isModelCatalogLoading={isModelCatalogLoading} mcpServers={mcpServers} selectedMCPServerIds={selectedMCPServerIds} onMCPSelectionChange={onMCPSelectionChange} diff --git a/site/src/pages/AgentsPage/components/AgentDetailView.stories.tsx b/site/src/pages/AgentsPage/components/AgentDetailView.stories.tsx index 965568b58f..add36f96f0 100644 --- a/site/src/pages/AgentsPage/components/AgentDetailView.stories.tsx +++ b/site/src/pages/AgentsPage/components/AgentDetailView.stories.tsx @@ -111,8 +111,6 @@ const StoryAgentDetailView: FC = ({ editing, ...overrides }) => { modelOptions: defaultModelOptions, modelSelectorPlaceholder: "Select a model", hasModelOptions: true, - inputStatusText: null as string | null, - modelCatalogStatusMessage: null as string | null, compressionThreshold: undefined as number | undefined, isInputDisabled: false, isSubmissionPending: false, @@ -276,7 +274,6 @@ export const NoModelOptions: Story = { ), @@ -308,8 +305,6 @@ export const Loading: Story = { modelOptions={defaultModelOptions} modelSelectorPlaceholder="Select a model" hasModelOptions - inputStatusText={null} - modelCatalogStatusMessage={null} isSidebarCollapsed={false} onToggleSidebarCollapsed={fn()} showRightPanel={false} @@ -328,8 +323,6 @@ export const LoadingWithModelOptions: Story = { modelOptions={defaultModelOptions} modelSelectorPlaceholder="Select a model" hasModelOptions - inputStatusText={null} - modelCatalogStatusMessage={null} isSidebarCollapsed={false} onToggleSidebarCollapsed={fn()} showRightPanel={false} @@ -347,8 +340,6 @@ export const LoadingWithRightPanel: Story = { modelOptions={defaultModelOptions} modelSelectorPlaceholder="Select a model" hasModelOptions - inputStatusText={null} - modelCatalogStatusMessage={null} isSidebarCollapsed={false} onToggleSidebarCollapsed={fn()} showRightPanel @@ -367,8 +358,6 @@ export const LoadingSidebarCollapsed: Story = { modelOptions={defaultModelOptions} modelSelectorPlaceholder="Select a model" hasModelOptions - inputStatusText={null} - modelCatalogStatusMessage={null} isSidebarCollapsed onToggleSidebarCollapsed={fn()} showRightPanel={false} diff --git a/site/src/pages/AgentsPage/components/AgentDetailView.tsx b/site/src/pages/AgentsPage/components/AgentDetailView.tsx index ee5b05c17c..5ecc25bd99 100644 --- a/site/src/pages/AgentsPage/components/AgentDetailView.tsx +++ b/site/src/pages/AgentsPage/components/AgentDetailView.tsx @@ -73,8 +73,7 @@ interface AgentDetailViewProps { modelOptions: readonly ModelSelectorOption[]; modelSelectorPlaceholder: string; hasModelOptions: boolean; - inputStatusText: string | null; - modelCatalogStatusMessage: string | null; + isModelCatalogLoading?: boolean; compressionThreshold: number | undefined; isInputDisabled: boolean; isSubmissionPending: boolean; @@ -152,8 +151,7 @@ export const AgentDetailView: FC = ({ modelOptions, modelSelectorPlaceholder, hasModelOptions, - inputStatusText, - modelCatalogStatusMessage, + isModelCatalogLoading = false, compressionThreshold, isInputDisabled, isSubmissionPending, @@ -302,8 +300,7 @@ export const AgentDetailView: FC = ({ onModelChange={setSelectedModel} modelOptions={modelOptions} modelSelectorPlaceholder={modelSelectorPlaceholder} - inputStatusText={inputStatusText} - modelCatalogStatusMessage={modelCatalogStatusMessage} + isModelCatalogLoading={isModelCatalogLoading} inputRef={editing.chatInputRef} initialValue={editing.editorInitialValue} onContentChange={editing.handleContentChange} @@ -372,8 +369,7 @@ interface AgentDetailLoadingViewProps { modelOptions: readonly ModelSelectorOption[]; modelSelectorPlaceholder: string; hasModelOptions: boolean; - inputStatusText: string | null; - modelCatalogStatusMessage: string | null; + isModelCatalogLoading?: boolean; isSidebarCollapsed: boolean; onToggleSidebarCollapsed: () => void; showRightPanel: boolean; @@ -387,8 +383,7 @@ export const AgentDetailLoadingView: FC = ({ modelOptions, modelSelectorPlaceholder, hasModelOptions, - inputStatusText, - modelCatalogStatusMessage, + isModelCatalogLoading = false, isSidebarCollapsed, onToggleSidebarCollapsed, showRightPanel, @@ -439,11 +434,10 @@ export const AgentDetailLoadingView: FC = ({ onModelChange={setSelectedModel} modelOptions={modelOptions} modelSelectorPlaceholder={modelSelectorPlaceholder} + isModelCatalogLoading={isModelCatalogLoading} hasModelOptions={hasModelOptions} - inputStatusText={inputStatusText} - modelCatalogStatusMessage={modelCatalogStatusMessage} /> - + {" "} {showRightPanel && ( { - if (modelOptions.length > 0) { - return null; - } - if (isModelCatalogLoading) { - return "Loading model catalog..."; - } - if (hasModelCatalogError) { - return "Model catalog unavailable. Unable to verify model availability."; - } - if (hasConfiguredModelsInCatalog(catalog)) { - return "Models are configured but unavailable. Check provider settings."; - } - return "No chat models are configured. Ask an admin to configure one."; + return "No Models Configured"; };