import { agentChatUsageStateV2 } from '@/ai/states/agentChatUsageStateV2'; import { currentAIChatThreadStateV2 } from '@/ai/states/currentAIChatThreadStateV2'; import { currentAIChatThreadTitleState } from '@/ai/states/currentAIChatThreadTitleState'; import { useOpenAskAIPageInCommandMenu } from '@/command-menu/hooks/useOpenAskAIPageInCommandMenu'; import { useRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilStateV2'; import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { useLingui } from '@lingui/react/macro'; import { isDefined } from 'twenty-shared/utils'; import { IconSparkles } from 'twenty-ui/display'; import { type AgentChatThread } from '~/generated-metadata/graphql'; const StyledThreadsList = styled.div` display: flex; flex-direction: column; gap: ${({ theme }) => theme.spacing(1)}; `; const StyledDateGroup = styled.div` margin-bottom: ${({ theme }) => theme.spacing(4)}; `; const StyledDateHeader = styled.div` color: ${({ theme }) => theme.font.color.light}; font-size: ${({ theme }) => theme.font.size.xs}; font-weight: 600; margin-bottom: ${({ theme }) => theme.spacing(1)}; `; const StyledThreadItem = styled.div<{ isSelected?: boolean }>` display: flex; align-items: center; gap: ${({ theme }) => theme.spacing(2)}; border-radius: ${({ theme }) => theme.border.radius.sm}; transition: all 0.2s ease; margin-bottom: ${({ theme }) => theme.spacing(1)}; border-left: 3px solid transparent; cursor: pointer; padding: ${({ theme }) => theme.spacing(1, 0.25)}; right: ${({ theme }) => theme.spacing(0.75)}; position: relative; width: calc(100% + ${({ theme }) => theme.spacing(0.25)}); &:hover { background: ${({ theme }) => theme.background.transparent.light}; } `; const StyledSparkleIcon = styled.div` align-items: center; background: ${({ theme }) => theme.background.transparent.blue}; border-radius: ${({ theme }) => theme.border.radius.sm}; display: flex; padding: ${({ theme }) => theme.spacing(1)}; justify-content: center; `; const StyledThreadContent = styled.div` flex: 1; min-width: 0; `; const StyledThreadTitle = styled.div` color: ${({ theme }) => theme.font.color.secondary}; font-size: ${({ theme }) => theme.font.size.md}; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; `; export const AIChatThreadGroup = ({ threads, title, }: { threads: AgentChatThread[]; title: string; }) => { const { t } = useLingui(); const theme = useTheme(); const [, setCurrentAIChatThread] = useRecoilStateV2( currentAIChatThreadStateV2, ); const setCurrentAIChatThreadTitle = useSetRecoilStateV2( currentAIChatThreadTitleState, ); const setAgentChatUsage = useSetRecoilStateV2(agentChatUsageStateV2); const { openAskAIPage } = useOpenAskAIPageInCommandMenu(); const handleThreadClick = (thread: AgentChatThread) => { setCurrentAIChatThread(thread.id); setCurrentAIChatThreadTitle(thread.title ?? null); const hasUsageData = (thread.conversationSize ?? 0) > 0 && isDefined(thread.contextWindowTokens); setAgentChatUsage( hasUsageData ? { lastMessage: null, conversationSize: thread.conversationSize ?? 0, contextWindowTokens: thread.contextWindowTokens ?? 0, inputTokens: thread.totalInputTokens, outputTokens: thread.totalOutputTokens, inputCredits: thread.totalInputCredits, outputCredits: thread.totalOutputCredits, } : null, ); openAskAIPage({ resetNavigationStack: false, }); }; if (threads.length === 0) { return null; } return ( {title} {threads.map((thread) => ( handleThreadClick(thread)} key={thread.id} > {thread.title || t`Untitled`} ))} ); };