diff --git a/apps/dashboard/src/components/agents/agent-behavior-section.tsx b/apps/dashboard/src/components/agents/agent-behavior-section.tsx new file mode 100644 index 00000000000..d7da479bf9d --- /dev/null +++ b/apps/dashboard/src/components/agents/agent-behavior-section.tsx @@ -0,0 +1,92 @@ +import { RiExpandUpDownLine } from 'react-icons/ri'; +import { HelpTooltipIndicator } from '@/components/primitives/help-tooltip-indicator'; +import { Switch } from '@/components/primitives/switch'; + +function SectionHeader({ children }: { children: React.ReactNode }) { + return ( +
+ + {children} + +
+ ); +} + +function ToggleRow({ label, children }: { label: string; children: React.ReactNode }) { + return ( +
+
+ {label} + +
+ {children} +
+ ); +} + +function EmojiPickerButton({ emoji }: { emoji: string }) { + return ( + + ); +} + +export function AgentBehaviorSection() { + return ( +
+ Agent behavior +
+ {/* + Interrupt mode and response timeout are not supported yet. + +
+ + + + + +
+ 30 + seconds +
+
+
+ */} + +
+ + + + + + + + + + + +
+
+
+ ); +} diff --git a/apps/dashboard/src/components/agents/agent-connected-overview.tsx b/apps/dashboard/src/components/agents/agent-connected-overview.tsx new file mode 100644 index 00000000000..e2f2b1b8e84 --- /dev/null +++ b/apps/dashboard/src/components/agents/agent-connected-overview.tsx @@ -0,0 +1,18 @@ +import type { AgentResponse } from '@/api/agents'; +import { AgentBehaviorSection } from './agent-behavior-section'; +import { ConnectedProvidersSection } from './connected-providers-section'; +import { RecentConversationsSection } from './recent-conversations-section'; + +type AgentConnectedOverviewProps = { + agent: AgentResponse; +}; + +export function AgentConnectedOverview({ agent }: AgentConnectedOverviewProps) { + return ( +
+ + + +
+ ); +} diff --git a/apps/dashboard/src/components/agents/agent-overview-tab.tsx b/apps/dashboard/src/components/agents/agent-overview-tab.tsx index 626bf893105..ef62432661f 100644 --- a/apps/dashboard/src/components/agents/agent-overview-tab.tsx +++ b/apps/dashboard/src/components/agents/agent-overview-tab.tsx @@ -1,4 +1,5 @@ import type { AgentResponse } from '@/api/agents'; +import { AgentConnectedOverview } from '@/components/agents/agent-connected-overview'; import { AgentSetupGuide } from '@/components/agents/agent-setup-guide'; import { AgentSidebarWidget } from '@/components/agents/agent-sidebar-widget'; @@ -7,10 +8,12 @@ type AgentOverviewTabProps = { }; export function AgentOverviewTab({ agent }: AgentOverviewTabProps) { + const isBridgeConnected = Boolean(agent.bridgeUrl || (agent.devBridgeActive && agent.devBridgeUrl)); + return (
- + {isBridgeConnected ? : }
); } diff --git a/apps/dashboard/src/components/agents/agent-setup-guide.tsx b/apps/dashboard/src/components/agents/agent-setup-guide.tsx index fd1ab8e5234..870dd61c386 100644 --- a/apps/dashboard/src/components/agents/agent-setup-guide.tsx +++ b/apps/dashboard/src/components/agents/agent-setup-guide.tsx @@ -1,7 +1,9 @@ import { ChatProviderIdEnum } from '@novu/shared'; +import { useQuery } from '@tanstack/react-query'; import { useCallback, useMemo, useState } from 'react'; import { RiExpandUpDownLine } from 'react-icons/ri'; -import { type AgentResponse } from '@/api/agents'; +import { type AgentResponse, getAgentIntegrationsQueryKey, listAgentIntegrations } from '@/api/agents'; +import { requireEnvironment, useEnvironment } from '@/context/environment/hooks'; import { useFetchIntegrations } from '@/hooks/use-fetch-integrations'; import { cn } from '@/utils/ui'; import { AgentCodeSetupSection } from './agent-code-setup-section'; @@ -23,12 +25,45 @@ function resolveProviderSetupGuide(providerId: string) { } } +function AgentSetupGuideComingSoon() { + + return ( +
+

Coming soon

+

+ In-dashboard setup steps will return here as we expand agent tooling. +

+
+ ); +} + export function AgentSetupGuide({ agent }: AgentSetupGuideProps) { const [isExpanded, setIsExpanded] = useState(true); const [selectedIntegrationId, setSelectedIntegrationId] = useState(undefined); const [isProviderComplete, setIsProviderComplete] = useState(false); + const { currentEnvironment } = useEnvironment(); const { integrations } = useFetchIntegrations(); + const agentIntegrationsQuery = useQuery({ + queryKey: getAgentIntegrationsQueryKey(currentEnvironment?._id, agent.identifier), + queryFn: () => + listAgentIntegrations({ + environment: requireEnvironment(currentEnvironment, 'No environment selected'), + agentIdentifier: agent.identifier, + limit: 100, + }), + enabled: Boolean(currentEnvironment && agent.identifier), + }); + + const hasConnectedIntegration = useMemo(() => { + if (isProviderComplete) return true; + + const links = agentIntegrationsQuery.data?.data; + if (!links?.length) return false; + + return links.some((link) => Boolean(link.connectedAt)); + }, [isProviderComplete, agentIntegrationsQuery.data?.data]); + const slackFromAgent = agent.integrations?.find((i) => i.providerId === ChatProviderIdEnum.Slack); const effectiveIntegrationId = selectedIntegrationId ?? slackFromAgent?.integrationId; @@ -56,6 +91,8 @@ export function AgentSetupGuide({ agent }: AgentSetupGuideProps) { setIsProviderComplete(true); }, []); + const isBridgeConnected = Boolean(agent.bridgeUrl || (agent.devBridgeActive && agent.devBridgeUrl)); + return (