Show tool execution messages in AI agent chat (#13117)

https://github.com/user-attachments/assets/c0a42726-50ac-496e-a993-9d6076a84a6a

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
Abdul Rahman
2025-07-10 11:15:05 +05:30
committed by GitHub
parent e6cdae5c27
commit 8310b4ff01
62 changed files with 1304 additions and 227 deletions

View File

@ -1,4 +1,5 @@
import { CommandMenu } from '@/command-menu/components/CommandMenu';
import { CommandMenuAskAIPage } from '@/command-menu/pages/ask-ai/components/CommandMenuAskAIPage';
import { CommandMenuCalendarEventPage } from '@/command-menu/pages/calendar-event/components/CommandMenuCalendarEventPage';
import { CommandMenuMessageThreadPage } from '@/command-menu/pages/message-thread/components/CommandMenuMessageThreadPage';
import { CommandMenuRecordPage } from '@/command-menu/pages/record-page/components/CommandMenuRecordPage';
@ -32,4 +33,5 @@ export const COMMAND_MENU_PAGES_CONFIG = new Map<
[CommandMenuPages.WorkflowStepView, <CommandMenuWorkflowViewStep />],
[CommandMenuPages.WorkflowRunStepView, <CommandMenuWorkflowRunViewStep />],
[CommandMenuPages.SearchRecords, <CommandMenuSearchRecordsPage />],
[CommandMenuPages.AskAI, <CommandMenuAskAIPage />],
]);

View File

@ -2,6 +2,7 @@ import { COMMAND_MENU_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/Com
import { SIDE_PANEL_FOCUS_ID } from '@/command-menu/constants/SidePanelFocusId';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { useCommandMenuHistory } from '@/command-menu/hooks/useCommandMenuHistory';
import { useOpenAskAIPageInCommandMenu } from '@/command-menu/hooks/useOpenAskAIPageInCommandMenu';
import { useOpenRecordsSearchPageInCommandMenu } from '@/command-menu/hooks/useOpenRecordsSearchPageInCommandMenu';
import { useSetGlobalCommandMenuContext } from '@/command-menu/hooks/useSetGlobalCommandMenuContext';
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
@ -12,15 +13,19 @@ import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeybo
import { useGlobalHotkeys } from '@/ui/utilities/hotkey/hooks/useGlobalHotkeys';
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { isNonEmptyString } from '@sniptt/guards';
import { useRecoilValue } from 'recoil';
import { Key } from 'ts-key-enum';
import { FeatureFlagKey } from '~/generated/graphql';
export const useCommandMenuHotKeys = () => {
const { toggleCommandMenu } = useCommandMenu();
const { openRecordsSearchPage } = useOpenRecordsSearchPageInCommandMenu();
const { openAskAIPage } = useOpenAskAIPageInCommandMenu();
const { goBackFromCommandMenu } = useCommandMenuHistory();
const { setGlobalCommandMenuContext } = useSetGlobalCommandMenuContext();
@ -31,6 +36,8 @@ export const useCommandMenuHotKeys = () => {
const commandMenuPage = useRecoilValue(commandMenuPageState);
const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
const contextStoreTargetedRecordsRuleComponent = useRecoilComponentValueV2(
contextStoreTargetedRecordsRuleComponentState,
COMMAND_MENU_COMPONENT_INSTANCE_ID,
@ -58,6 +65,20 @@ export const useCommandMenuHotKeys = () => {
},
);
useGlobalHotkeys(
['@'],
() => {
if (isAiEnabled) {
openAskAIPage();
}
},
false,
[openAskAIPage, isAiEnabled],
{
ignoreModifiers: true,
},
);
useHotkeysOnFocusedElement({
keys: [Key.Escape],
callback: () => {

View File

@ -0,0 +1,22 @@
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
import { t } from '@lingui/core/macro';
import { IconSparkles } from 'twenty-ui/display';
import { v4 } from 'uuid';
export const useOpenAskAIPageInCommandMenu = () => {
const { navigateCommandMenu } = useCommandMenu();
const openAskAIPage = () => {
navigateCommandMenu({
page: CommandMenuPages.AskAI,
pageTitle: t`Ask AI`,
pageIcon: IconSparkles,
pageId: v4(),
});
};
return {
openAskAIPage,
};
};

View File

@ -0,0 +1,37 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { AIChatTab } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/components/AIChatTab';
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
const StyledContainer = styled.div`
height: 100%;
width: 100%;
`;
const StyledEmptyState = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.secondary};
display: flex;
font-size: ${({ theme }) => theme.font.size.md};
height: 100%;
justify-content: center;
`;
export const CommandMenuAskAIPage = () => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const agentId = currentWorkspace?.defaultAgent?.id;
if (!agentId) {
return (
<StyledContainer>
<StyledEmptyState>No AI Agent found.</StyledEmptyState>
</StyledContainer>
);
}
return (
<StyledContainer>
<AIChatTab agentId={agentId} />
</StyledContainer>
);
};

View File

@ -11,4 +11,5 @@ export enum CommandMenuPages {
WorkflowStepEdit = 'workflow-step-edit',
WorkflowRunStepView = 'workflow-run-step-view',
SearchRecords = 'search-records',
AskAI = 'ask-ai',
}