AI tools to create a demo workspace (#18236)

This PR adds the necessary tool to create a demo workspace with :
relevant custom objects and fields, mock data and a real dashboard with
graph widgets.

It is still a bit under-optimized and slow but it works.

This PR also adds an AI tool that allows to see what happens in real
time, it navigates the app and waits when necessary.

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
Lucas Bordeau
2026-03-05 11:39:31 +01:00
committed by GitHub
parent a2f80d882b
commit 2a82df7073
84 changed files with 2449 additions and 315 deletions
@@ -1,5 +1,8 @@
import { useAgentChatContextOrThrow } from '@/ai/hooks/useAgentChatContextOrThrow';
import { agentChatInputState } from '@/ai/states/agentChatInputState';
import { AGENT_CHAT_STOP_EVENT_NAME } from '@/ai/constants/AgentChatStopEventName';
import { agentChatInputIsEmptySelector } from '@/ai/states/agentChatInputIsEmptySelector';
import { agentChatIsLoadingState } from '@/ai/states/agentChatIsLoadingState';
import { agentChatIsStreamingState } from '@/ai/states/agentChatIsStreamingState';
import { dispatchBrowserEvent } from '@/browser-event/utils/dispatchBrowserEvent';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { IconArrowUp, IconPlayerStop } from 'twenty-ui/display';
import { RoundedIconButton } from 'twenty-ui/input';
@@ -9,15 +12,24 @@ type SendMessageButtonProps = {
};
export const SendMessageButton = ({ onSend }: SendMessageButtonProps) => {
const agentChatInput = useAtomStateValue(agentChatInputState);
const { handleStop, isLoading, isStreaming } = useAgentChatContextOrThrow();
const agentChatInputIsEmpty = useAtomStateValue(
agentChatInputIsEmptySelector,
);
if (isStreaming) {
const agentChatIsLoading = useAtomStateValue(agentChatIsLoadingState);
const agentChatIsStreaming = useAtomStateValue(agentChatIsStreamingState);
const handleStopClick = () => {
dispatchBrowserEvent(AGENT_CHAT_STOP_EVENT_NAME);
};
if (agentChatIsStreaming) {
return (
<RoundedIconButton
Icon={IconPlayerStop}
size="medium"
onClick={() => handleStop()}
onClick={handleStopClick}
/>
);
}
@@ -27,7 +39,7 @@ export const SendMessageButton = ({ onSend }: SendMessageButtonProps) => {
Icon={IconArrowUp}
size="medium"
onClick={onSend}
disabled={!agentChatInput || isLoading}
disabled={agentChatInputIsEmpty || agentChatIsLoading}
/>
);
};