From 153739b9c345c039de4fc004b3222265bc13921d Mon Sep 17 00:00:00 2001 From: Antoine Moreaux Date: Tue, 22 Jul 2025 17:27:19 +0200 Subject: [PATCH] feat(ai): add current context to ai chat (#13315) ## TODO - [ ] add dropdown to use records from outside the context - [x] add loader for files chip - [x] add roleId where it's necessary - [x] Split AvatarChip in two components. One with the icon that will call the second with leftComponent. - [ ] Fix tests - [x] Fix UI regression on Search --- .../src/generated-metadata/graphql.ts | 342 +++++++++--------- .../modules/ai/components/AIChatMessage.tsx | 4 +- .../components/AIChatTab.tsx | 33 +- .../ai/components/AIChatThreadsList.tsx | 2 +- .../internal}/AIChatSkeletonLoader.tsx | 0 .../internal/AgentChatContextPreview.tsx | 93 +++++ .../AgentChatContextRecordPreview.tsx | 104 ++++++ .../internal/AgentChatFilePreview.tsx | 47 +++ .../internal/AgentChatFileUploadButton.tsx} | 8 +- .../components/internal/SendMessageButton.tsx | 29 ++ .../SendMessageWithRecordsContextButton.tsx | 14 + .../constants/agent-chat-message-role.ts | 0 .../constants/output-field-type-options.ts | 0 .../graphql/mutations/assignRoleToAgent.ts | 0 .../graphql/mutations/removeRoleFromAgent.ts | 0 .../graphql/mutations/updateOneAgent.ts | 0 .../graphql/queries/findOneAgent.ts | 0 .../modules/ai/hooks/useAIChatFileUpload.ts | 4 +- .../hooks/useAgentChat.ts | 58 ++- .../hooks/useAgentRoleAssignment.ts | 0 .../hooks/useAgentUpdateFormState.ts | 0 .../hooks/useAiAgentOutputSchema.ts | 2 +- .../hooks/useAiModelOptions.ts | 0 .../rest-api}/agent-chat-apollo.api.ts | 0 .../states/agentChatInputState.ts | 0 .../states/agentChatMessagesComponentState.ts | 0 ...ChatObjectMetadataAndRecordContextState.ts | 14 + .../agentChatSelectedFilesComponentState.ts | 2 +- .../agentChatUploadedFilesComponentState.ts | 2 +- .../states/agentStreamingMessageState.ts | 0 .../isAgentChatCurrentContextActiveState.ts | 12 + .../utils/__tests__/getFieldIcon.test.ts | 0 .../parseAgentStreamingChunk.test.ts | 0 .../utils/getFieldIcon.ts | 0 .../utils/parseAgentStreamingChunk.ts | 0 .../components/CommandMenuContextChip.tsx | 88 ----- .../CommandMenuContextChipGroups.tsx | 18 +- ...nuContextChipGroupsWithRecordSelection.tsx | 4 +- .../CommandMenuContextRecordsChip.tsx | 4 +- .../components/CommandMenuTopBar.tsx | 4 +- .../components/CommandMenuAskAIPage.tsx | 2 +- .../src/modules/file/components/FileIcon.tsx | 38 +- .../modules/file/utils/fileIconMappings.ts | 40 ++ .../hooks/useGetObjectMetadataItemById.ts | 28 ++ .../object-record/components/RecordChip.tsx | 35 +- .../components/RecordBoardCardHeader.tsx | 4 +- .../SettingsAdminWorkspaceContent.tsx | 24 +- .../field/display/components/ActorDisplay.tsx | 21 +- .../components/AgentChatFilePreview.tsx | 103 ------ .../AgentChatSelectedFilesPreview.tsx | 75 ---- .../components/WorkflowEditActionAiAgent.tsx | 10 +- .../WorkflowOutputFieldTypeSelector.tsx | 2 +- .../WorkflowOutputSchemaBuilder.tsx | 2 +- .../agent/agent-chat.controller.ts | 14 +- .../agent/agent-execution.service.ts | 118 +++++- .../agent/agent-streaming.service.ts | 19 +- .../metadata-modules/agent/agent.exception.ts | 1 + ...ordIdsByObjectMetadataNameSingular.type.ts | 4 + .../src/components/avatar-chip/AvatarChip.tsx | 138 +++++-- .../avatar-chip/AvatarChipLeftComponent.tsx | 74 ---- .../components/avatar-chip/LinkAvatarChip.tsx | 64 ---- .../avatar-chip/MultipleAvatarChip.tsx | 61 ++++ .../__stories__/AvatarChip.stories.tsx | 79 ++++ .../MultipleAvatarChip.stories.tsx} | 14 +- .../types/AvatarChipsCommonProps.type.ts | 9 - .../types/AvatarChipsVariant.type.ts | 4 - .../twenty-ui/src/components/chip/Chip.tsx | 22 +- .../chip/__stories__/EntityChip.stories.tsx | 29 -- packages/twenty-ui/src/components/index.ts | 8 +- 69 files changed, 1111 insertions(+), 819 deletions(-) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/components/AIChatTab.tsx (78%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action/components => ai/components/internal}/AIChatSkeletonLoader.tsx (100%) create mode 100644 packages/twenty-front/src/modules/ai/components/internal/AgentChatContextPreview.tsx create mode 100644 packages/twenty-front/src/modules/ai/components/internal/AgentChatContextRecordPreview.tsx create mode 100644 packages/twenty-front/src/modules/ai/components/internal/AgentChatFilePreview.tsx rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action/components/AgentChatFileUpload.tsx => ai/components/internal/AgentChatFileUploadButton.tsx} (75%) create mode 100644 packages/twenty-front/src/modules/ai/components/internal/SendMessageButton.tsx create mode 100644 packages/twenty-front/src/modules/ai/components/internal/SendMessageWithRecordsContextButton.tsx rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/constants/agent-chat-message-role.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/constants/output-field-type-options.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/graphql/mutations/assignRoleToAgent.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/graphql/mutations/removeRoleFromAgent.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/graphql/mutations/updateOneAgent.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/graphql/queries/findOneAgent.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/hooks/useAgentChat.ts (74%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/hooks/useAgentRoleAssignment.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/hooks/useAgentUpdateFormState.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/hooks/useAiAgentOutputSchema.ts (93%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/hooks/useAiModelOptions.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action/api => ai/rest-api}/agent-chat-apollo.api.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/states/agentChatInputState.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/states/agentChatMessagesComponentState.ts (100%) create mode 100644 packages/twenty-front/src/modules/ai/states/agentChatObjectMetadataAndRecordContextState.ts rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/states/agentChatSelectedFilesComponentState.ts (68%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/states/agentChatUploadedFilesComponentState.ts (71%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/states/agentStreamingMessageState.ts (100%) create mode 100644 packages/twenty-front/src/modules/ai/states/isAgentChatCurrentContextActiveState.ts rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/utils/__tests__/getFieldIcon.test.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/utils/__tests__/parseAgentStreamingChunk.test.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/utils/getFieldIcon.ts (100%) rename packages/twenty-front/src/modules/{workflow/workflow-steps/workflow-actions/ai-agent-action => ai}/utils/parseAgentStreamingChunk.ts (100%) delete mode 100644 packages/twenty-front/src/modules/command-menu/components/CommandMenuContextChip.tsx create mode 100644 packages/twenty-front/src/modules/file/utils/fileIconMappings.ts create mode 100644 packages/twenty-front/src/modules/object-metadata/hooks/useGetObjectMetadataItemById.ts delete mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/AgentChatFilePreview.tsx delete mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/AgentChatSelectedFilesPreview.tsx create mode 100644 packages/twenty-server/src/engine/metadata-modules/agent/types/recordIdsByObjectMetadataNameSingular.type.ts delete mode 100644 packages/twenty-ui/src/components/avatar-chip/AvatarChipLeftComponent.tsx delete mode 100644 packages/twenty-ui/src/components/avatar-chip/LinkAvatarChip.tsx create mode 100644 packages/twenty-ui/src/components/avatar-chip/MultipleAvatarChip.tsx create mode 100644 packages/twenty-ui/src/components/avatar-chip/__stories__/AvatarChip.stories.tsx rename packages/{twenty-front/src/modules/command-menu/components/__stories__/CommandMenuContextChip.stories.tsx => twenty-ui/src/components/avatar-chip/__stories__/MultipleAvatarChip.stories.tsx} (56%) delete mode 100644 packages/twenty-ui/src/components/avatar-chip/types/AvatarChipsCommonProps.type.ts delete mode 100644 packages/twenty-ui/src/components/avatar-chip/types/AvatarChipsVariant.type.ts delete mode 100644 packages/twenty-ui/src/components/chip/__stories__/EntityChip.stories.tsx diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index fc3365440..836979e30 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -2971,6 +2971,14 @@ export type WorkspaceUrlsAndId = { workspaceUrls: WorkspaceUrls; }; +export type AssignRoleToAgentMutationVariables = Exact<{ + agentId: Scalars['UUID']; + roleId: Scalars['UUID']; +}>; + + +export type AssignRoleToAgentMutation = { __typename?: 'Mutation', assignRoleToAgent: boolean }; + export type CreateAgentChatThreadMutationVariables = Exact<{ input: CreateAgentChatThreadInput; }>; @@ -2978,6 +2986,27 @@ export type CreateAgentChatThreadMutationVariables = Exact<{ export type CreateAgentChatThreadMutation = { __typename?: 'Mutation', createAgentChatThread: { __typename?: 'AgentChatThread', id: any, agentId: any, title?: string | null, createdAt: string, updatedAt: string } }; +export type RemoveRoleFromAgentMutationVariables = Exact<{ + agentId: Scalars['UUID']; +}>; + + +export type RemoveRoleFromAgentMutation = { __typename?: 'Mutation', removeRoleFromAgent: boolean }; + +export type UpdateOneAgentMutationVariables = Exact<{ + input: UpdateAgentInput; +}>; + + +export type UpdateOneAgentMutation = { __typename?: 'Mutation', updateOneAgent: { __typename?: 'Agent', id: any, name: string, description?: string | null, prompt: string, modelId: string, responseFormat?: any | null } }; + +export type FindOneAgentQueryVariables = Exact<{ + id: Scalars['UUID']; +}>; + + +export type FindOneAgentQuery = { __typename?: 'Query', findOneAgent: { __typename?: 'Agent', id: any, name: string, description?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: any | null } }; + export type GetAgentChatMessagesQueryVariables = Exact<{ threadId: Scalars['String']; }>; @@ -3795,35 +3824,6 @@ export type UpdateWorkflowVersionStepMutationVariables = Exact<{ export type UpdateWorkflowVersionStepMutation = { __typename?: 'Mutation', updateWorkflowVersionStep: { __typename?: 'WorkflowAction', id: any, name: string, type: string, settings: any, valid: boolean, nextStepIds?: Array | null } }; -export type AssignRoleToAgentMutationVariables = Exact<{ - agentId: Scalars['UUID']; - roleId: Scalars['UUID']; -}>; - - -export type AssignRoleToAgentMutation = { __typename?: 'Mutation', assignRoleToAgent: boolean }; - -export type RemoveRoleFromAgentMutationVariables = Exact<{ - agentId: Scalars['UUID']; -}>; - - -export type RemoveRoleFromAgentMutation = { __typename?: 'Mutation', removeRoleFromAgent: boolean }; - -export type UpdateOneAgentMutationVariables = Exact<{ - input: UpdateAgentInput; -}>; - - -export type UpdateOneAgentMutation = { __typename?: 'Mutation', updateOneAgent: { __typename?: 'Agent', id: any, name: string, description?: string | null, prompt: string, modelId: string, responseFormat?: any | null } }; - -export type FindOneAgentQueryVariables = Exact<{ - id: Scalars['UUID']; -}>; - - -export type FindOneAgentQuery = { __typename?: 'Query', findOneAgent: { __typename?: 'Agent', id: any, name: string, description?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: any | null } }; - export type SubmitFormStepMutationVariables = Exact<{ input: SubmitFormStepInput; }>; @@ -4169,6 +4169,38 @@ ${ObjectPermissionFragmentFragmentDoc} ${WorkspaceUrlsFragmentFragmentDoc} ${RoleFragmentFragmentDoc} ${AvailableWorkspacesFragmentFragmentDoc}`; +export const AssignRoleToAgentDocument = gql` + mutation AssignRoleToAgent($agentId: UUID!, $roleId: UUID!) { + assignRoleToAgent(agentId: $agentId, roleId: $roleId) +} + `; +export type AssignRoleToAgentMutationFn = Apollo.MutationFunction; + +/** + * __useAssignRoleToAgentMutation__ + * + * To run a mutation, you first call `useAssignRoleToAgentMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useAssignRoleToAgentMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [assignRoleToAgentMutation, { data, loading, error }] = useAssignRoleToAgentMutation({ + * variables: { + * agentId: // value for 'agentId' + * roleId: // value for 'roleId' + * }, + * }); + */ +export function useAssignRoleToAgentMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(AssignRoleToAgentDocument, options); + } +export type AssignRoleToAgentMutationHookResult = ReturnType; +export type AssignRoleToAgentMutationResult = Apollo.MutationResult; +export type AssignRoleToAgentMutationOptions = Apollo.BaseMutationOptions; export const CreateAgentChatThreadDocument = gql` mutation CreateAgentChatThread($input: CreateAgentChatThreadInput!) { createAgentChatThread(input: $input) { @@ -4206,6 +4238,116 @@ export function useCreateAgentChatThreadMutation(baseOptions?: Apollo.MutationHo export type CreateAgentChatThreadMutationHookResult = ReturnType; export type CreateAgentChatThreadMutationResult = Apollo.MutationResult; export type CreateAgentChatThreadMutationOptions = Apollo.BaseMutationOptions; +export const RemoveRoleFromAgentDocument = gql` + mutation RemoveRoleFromAgent($agentId: UUID!) { + removeRoleFromAgent(agentId: $agentId) +} + `; +export type RemoveRoleFromAgentMutationFn = Apollo.MutationFunction; + +/** + * __useRemoveRoleFromAgentMutation__ + * + * To run a mutation, you first call `useRemoveRoleFromAgentMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useRemoveRoleFromAgentMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [removeRoleFromAgentMutation, { data, loading, error }] = useRemoveRoleFromAgentMutation({ + * variables: { + * agentId: // value for 'agentId' + * }, + * }); + */ +export function useRemoveRoleFromAgentMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(RemoveRoleFromAgentDocument, options); + } +export type RemoveRoleFromAgentMutationHookResult = ReturnType; +export type RemoveRoleFromAgentMutationResult = Apollo.MutationResult; +export type RemoveRoleFromAgentMutationOptions = Apollo.BaseMutationOptions; +export const UpdateOneAgentDocument = gql` + mutation UpdateOneAgent($input: UpdateAgentInput!) { + updateOneAgent(input: $input) { + id + name + description + prompt + modelId + responseFormat + } +} + `; +export type UpdateOneAgentMutationFn = Apollo.MutationFunction; + +/** + * __useUpdateOneAgentMutation__ + * + * To run a mutation, you first call `useUpdateOneAgentMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateOneAgentMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateOneAgentMutation, { data, loading, error }] = useUpdateOneAgentMutation({ + * variables: { + * input: // value for 'input' + * }, + * }); + */ +export function useUpdateOneAgentMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateOneAgentDocument, options); + } +export type UpdateOneAgentMutationHookResult = ReturnType; +export type UpdateOneAgentMutationResult = Apollo.MutationResult; +export type UpdateOneAgentMutationOptions = Apollo.BaseMutationOptions; +export const FindOneAgentDocument = gql` + query FindOneAgent($id: UUID!) { + findOneAgent(input: {id: $id}) { + id + name + description + prompt + modelId + responseFormat + roleId + } +} + `; + +/** + * __useFindOneAgentQuery__ + * + * To run a query within a React component, call `useFindOneAgentQuery` and pass it any options that fit your needs. + * When your component renders, `useFindOneAgentQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useFindOneAgentQuery({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useFindOneAgentQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(FindOneAgentDocument, options); + } +export function useFindOneAgentLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(FindOneAgentDocument, options); + } +export type FindOneAgentQueryHookResult = ReturnType; +export type FindOneAgentLazyQueryHookResult = ReturnType; +export type FindOneAgentQueryResult = Apollo.QueryResult; export const GetAgentChatMessagesDocument = gql` query GetAgentChatMessages($threadId: String!) { agentChatMessages(threadId: $threadId) { @@ -8463,148 +8605,6 @@ export function useUpdateWorkflowVersionStepMutation(baseOptions?: Apollo.Mutati export type UpdateWorkflowVersionStepMutationHookResult = ReturnType; export type UpdateWorkflowVersionStepMutationResult = Apollo.MutationResult; export type UpdateWorkflowVersionStepMutationOptions = Apollo.BaseMutationOptions; -export const AssignRoleToAgentDocument = gql` - mutation AssignRoleToAgent($agentId: UUID!, $roleId: UUID!) { - assignRoleToAgent(agentId: $agentId, roleId: $roleId) -} - `; -export type AssignRoleToAgentMutationFn = Apollo.MutationFunction; - -/** - * __useAssignRoleToAgentMutation__ - * - * To run a mutation, you first call `useAssignRoleToAgentMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useAssignRoleToAgentMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [assignRoleToAgentMutation, { data, loading, error }] = useAssignRoleToAgentMutation({ - * variables: { - * agentId: // value for 'agentId' - * roleId: // value for 'roleId' - * }, - * }); - */ -export function useAssignRoleToAgentMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(AssignRoleToAgentDocument, options); - } -export type AssignRoleToAgentMutationHookResult = ReturnType; -export type AssignRoleToAgentMutationResult = Apollo.MutationResult; -export type AssignRoleToAgentMutationOptions = Apollo.BaseMutationOptions; -export const RemoveRoleFromAgentDocument = gql` - mutation RemoveRoleFromAgent($agentId: UUID!) { - removeRoleFromAgent(agentId: $agentId) -} - `; -export type RemoveRoleFromAgentMutationFn = Apollo.MutationFunction; - -/** - * __useRemoveRoleFromAgentMutation__ - * - * To run a mutation, you first call `useRemoveRoleFromAgentMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useRemoveRoleFromAgentMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [removeRoleFromAgentMutation, { data, loading, error }] = useRemoveRoleFromAgentMutation({ - * variables: { - * agentId: // value for 'agentId' - * }, - * }); - */ -export function useRemoveRoleFromAgentMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(RemoveRoleFromAgentDocument, options); - } -export type RemoveRoleFromAgentMutationHookResult = ReturnType; -export type RemoveRoleFromAgentMutationResult = Apollo.MutationResult; -export type RemoveRoleFromAgentMutationOptions = Apollo.BaseMutationOptions; -export const UpdateOneAgentDocument = gql` - mutation UpdateOneAgent($input: UpdateAgentInput!) { - updateOneAgent(input: $input) { - id - name - description - prompt - modelId - responseFormat - } -} - `; -export type UpdateOneAgentMutationFn = Apollo.MutationFunction; - -/** - * __useUpdateOneAgentMutation__ - * - * To run a mutation, you first call `useUpdateOneAgentMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdateOneAgentMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [updateOneAgentMutation, { data, loading, error }] = useUpdateOneAgentMutation({ - * variables: { - * input: // value for 'input' - * }, - * }); - */ -export function useUpdateOneAgentMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateOneAgentDocument, options); - } -export type UpdateOneAgentMutationHookResult = ReturnType; -export type UpdateOneAgentMutationResult = Apollo.MutationResult; -export type UpdateOneAgentMutationOptions = Apollo.BaseMutationOptions; -export const FindOneAgentDocument = gql` - query FindOneAgent($id: UUID!) { - findOneAgent(input: {id: $id}) { - id - name - description - prompt - modelId - responseFormat - roleId - } -} - `; - -/** - * __useFindOneAgentQuery__ - * - * To run a query within a React component, call `useFindOneAgentQuery` and pass it any options that fit your needs. - * When your component renders, `useFindOneAgentQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useFindOneAgentQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useFindOneAgentQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(FindOneAgentDocument, options); - } -export function useFindOneAgentLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(FindOneAgentDocument, options); - } -export type FindOneAgentQueryHookResult = ReturnType; -export type FindOneAgentLazyQueryHookResult = ReturnType; -export type FindOneAgentQueryResult = Apollo.QueryResult; export const SubmitFormStepDocument = gql` mutation SubmitFormStep($input: SubmitFormStepInput!) { submitFormStep(input: $input) diff --git a/packages/twenty-front/src/modules/ai/components/AIChatMessage.tsx b/packages/twenty-front/src/modules/ai/components/AIChatMessage.tsx index 05f894bb7..3cf0d370a 100644 --- a/packages/twenty-front/src/modules/ai/components/AIChatMessage.tsx +++ b/packages/twenty-front/src/modules/ai/components/AIChatMessage.tsx @@ -3,8 +3,8 @@ import styled from '@emotion/styled'; import { Avatar, IconDotsVertical, IconSparkles } from 'twenty-ui/display'; import { LightCopyIconButton } from '@/object-record/record-field/components/LightCopyIconButton'; -import { AgentChatFilePreview } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/components/AgentChatFilePreview'; -import { AgentChatMessageRole } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/constants/agent-chat-message-role'; +import { AgentChatFilePreview } from '@/ai/components/internal/AgentChatFilePreview'; +import { AgentChatMessageRole } from '@/ai/constants/agent-chat-message-role'; import { AgentChatMessage } from '~/generated/graphql'; import { beautifyPastDateRelativeToNow } from '~/utils/date-utils'; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/AIChatTab.tsx b/packages/twenty-front/src/modules/ai/components/AIChatTab.tsx similarity index 78% rename from packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/AIChatTab.tsx rename to packages/twenty-front/src/modules/ai/components/AIChatTab.tsx index 398f4a57e..bb39232f6 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/AIChatTab.tsx +++ b/packages/twenty-front/src/modules/ai/components/AIChatTab.tsx @@ -7,7 +7,7 @@ import { useCreateNewAIChatThread } from '@/ai/hooks/useCreateNewAIChatThread'; import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; -import { AgentChatFileUpload } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/components/AgentChatFileUpload'; +import { AgentChatFileUploadButton } from '@/ai/components/internal/AgentChatFileUploadButton'; import { AIChatEmptyState } from '@/ai/components/AIChatEmptyState'; import { AIChatMessage } from '@/ai/components/AIChatMessage'; @@ -16,8 +16,12 @@ import { t } from '@lingui/core/macro'; import { useState } from 'react'; import { Button } from 'twenty-ui/input'; import { useAgentChat } from '../hooks/useAgentChat'; -import { AIChatSkeletonLoader } from './AIChatSkeletonLoader'; -import { AgentChatSelectedFilesPreview } from './AgentChatSelectedFilesPreview'; +import { AIChatSkeletonLoader } from '@/ai/components/internal/AIChatSkeletonLoader'; +import { AgentChatContextPreview } from '@/ai/components/internal/AgentChatContextPreview'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState'; +import { SendMessageWithRecordsContextButton } from '@/ai/components/internal/SendMessageWithRecordsContextButton'; +import { SendMessageButton } from '@/ai/components/internal/SendMessageButton'; const StyledContainer = styled.div<{ isDraggingFile: boolean }>` background: ${({ theme }) => theme.background.primary}; @@ -63,10 +67,13 @@ export const AIChatTab = ({ }) => { const [isDraggingFile, setIsDraggingFile] = useState(false); + const contextStoreCurrentObjectMetadataItemId = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataItemIdComponentState, + ); + const { messages, isLoading, - handleSendMessage, input, handleInputChange, agentStreamingMessage, @@ -105,7 +112,7 @@ export const AIChatTab = ({ {isLoading && messages.length === 0 && } - +