From d709467902a3d8e28530b9438f6d0b0b35c57d5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 2 Jul 2026 14:50:57 +0200 Subject: [PATCH] feat(ai): surface AI chat stream failures through one typed error channel (#22434) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Context Investigating a report where the AI chat showed only a `...` spinner while the network response clearly contained `No AI models are available`. Root cause: terminal stream failures reach the client on **two mismatched channels**. | Representation | Persisted (survives reload) | Rendered by client | |---|---|---| | AI-SDK `error` chunk (inside `stream-chunk`) | ✅ RPUSH'd to Redis | ❌ dropped by `readUIMessageStream` (no message part, no error state) | | typed `stream-error` event | ❌ never persisted | ✅ sets the error atom | Live, the `stream-error` event renders. But on reload, `chatStreamCatchupChunks` replays only the persisted **error chunk** — which the reducer discards — and the streaming indicator never clears. ## Change Collapse to a single typed error contract: - **Suppress the opaque `error` chunk** in the stream job; every failure is surfaced through the typed `stream-error` event. Errors are mapped via `mapErrorToStreamError` so an `AiException` keeps its `AiExceptionCode` (e.g. `API_KEY_NOT_CONFIGURED` → the existing "AI not configured" banner) instead of leaking a raw string. - **Persist the terminal error** next to the accumulated chunks and expose it as an explicit `error { code message }` field on `ChatStreamCatchupChunks`, so a client catching up after a reload recovers it — no dependency on the AI SDK's internal chunk shape. - **Reset per-thread stream state at job start**, so a failed turn's leftover chunks/error never replay on the next stream. - **Client replays the catchup error** as a terminal `stream-error` event, which clears the streaming indicator and renders the error (fixes the infinite spinner on a stream that ended in error). ## Notes - `ChatStreamError` is a new metadata GraphQL type; generated types (twenty-front metadata + client-sdk) were hand-updated to keep the tree consistent and will be reconciled by CI's `graphql:generate` check if anything differs. - Server unit test added for the error mapping. No schema/DB migration. ## Test plan - [ ] With no AI provider configured, send a chat message → error renders immediately (not a spinner). - [ ] Reload the thread → the error still renders (recovered from catchup), indicator not spinning. - [ ] Configure a provider and send again → normal streaming; no stale error from the previous failed turn. Review in cubic --- .../src/metadata/generated/schema.graphql | 7 + .../src/metadata/generated/schema.ts | 25 + .../src/metadata/generated/types.ts | 470 +++++++++--------- .../src/generated-metadata/graphql.ts | 27 +- .../AgentChatMessagesFetchEffect.tsx | 18 +- .../ai/components/AiChatErrorMessage.tsx | 19 +- .../ai/components/AiChatErrorRenderer.tsx | 8 +- .../AiChatErrorUnderMessageList.tsx | 4 +- .../ai/graphql/mutations/retryChatMessage.ts | 11 + .../ai/graphql/queries/getChatMessages.ts | 4 + .../modules/ai/hooks/useRetryChatMessage.ts | 53 ++ packages/twenty-server/jest.config.mjs | 5 +- ...-last-stream-error-to-agent-chat-thread.ts | 21 + ...agent-chat-thread.instance-command.spec.ts | 37 ++ ...at-thread-upgrade-command-name.constant.ts | 4 + .../instance-commands.constant.ts | 2 + .../dtos/chat-stream-catchup-chunks.dto.ts | 5 + .../ai/ai-chat/dtos/chat-stream-error.dto.ts | 10 + .../entities/agent-chat-thread.entity.ts | 10 + .../ai/ai-chat/jobs/stream-agent-chat.job.ts | 50 +- .../ai-chat/resolvers/agent-chat.resolver.ts | 52 +- ...agent-chat-streaming.service.retry.spec.ts | 142 ++++++ .../agent-chat-event-publisher.service.ts | 6 + .../services/agent-chat-streaming.service.ts | 101 +++- .../ai/ai-chat/services/agent-chat.service.ts | 31 ++ ...gent-chat-thread-last-stream-error.type.ts | 5 + .../map-error-to-stream-error.util.spec.ts | 49 ++ .../utils/map-error-to-stream-error.util.ts | 28 ++ .../metadata-modules/ai/ai.exception.ts | 3 + .../ai-graphql-api-exception-handler.util.ts | 1 + 30 files changed, 965 insertions(+), 243 deletions(-) create mode 100644 packages/twenty-front/src/modules/ai/graphql/mutations/retryChatMessage.ts create mode 100644 packages/twenty-front/src/modules/ai/hooks/useRetryChatMessage.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version-command/2-19/2-19-instance-command-fast-1821000000000-add-last-stream-error-to-agent-chat-thread.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version-command/2-19/__tests__/add-last-stream-error-to-agent-chat-thread.instance-command.spec.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version-command/2-19/add-last-stream-error-to-agent-chat-thread-upgrade-command-name.constant.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/dtos/chat-stream-error.dto.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/services/__tests__/agent-chat-streaming.service.retry.spec.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/types/agent-chat-thread-last-stream-error.type.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/utils/__tests__/map-error-to-stream-error.util.spec.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/utils/map-error-to-stream-error.util.ts diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql index 46703a0519..0072461209 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql @@ -2824,9 +2824,15 @@ type AiSystemPromptPreview { estimatedTokenCount: Int! } +type ChatStreamError { + code: String! + message: String! +} + type ChatStreamCatchupChunks { chunks: [JSON!]! maxSeq: Int! + error: ChatStreamError } type SendChatMessageResult { @@ -3373,6 +3379,7 @@ type Mutation { updateCalendarChannel(input: UpdateCalendarChannelInput!): CalendarChannel! createChatThread: AgentChatThread! sendChatMessage(threadId: UUID!, text: String!, messageId: UUID!, browsingContext: JSON, modelId: String, fileAttachments: [FileAttachmentInput!]): SendChatMessageResult! + retryChatMessage(threadId: UUID!, modelId: String): SendChatMessageResult! stopAgentChatStream(threadId: UUID!): Boolean! renameChatThread(id: UUID!, title: String!): AgentChatThread! archiveChatThread(id: UUID!): AgentChatThread! diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.ts b/packages/twenty-client-sdk/src/metadata/generated/schema.ts index 462cdbbc63..d8bce60e1c 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.ts @@ -2508,9 +2508,16 @@ export interface AiSystemPromptPreview { __typename: 'AiSystemPromptPreview' } +export interface ChatStreamError { + code: Scalars['String'] + message: Scalars['String'] + __typename: 'ChatStreamError' +} + export interface ChatStreamCatchupChunks { chunks: Scalars['JSON'][] maxSeq: Scalars['Int'] + error?: ChatStreamError __typename: 'ChatStreamCatchupChunks' } @@ -2904,6 +2911,7 @@ export interface Mutation { updateCalendarChannel: CalendarChannel createChatThread: AgentChatThread sendChatMessage: SendChatMessageResult + retryChatMessage: SendChatMessageResult stopAgentChatStream: Scalars['Boolean'] renameChatThread: AgentChatThread archiveChatThread: AgentChatThread @@ -5632,9 +5640,17 @@ export interface AiSystemPromptPreviewGenqlSelection{ __scalar?: boolean | number } +export interface ChatStreamErrorGenqlSelection{ + code?: boolean | number + message?: boolean | number + __typename?: boolean | number + __scalar?: boolean | number +} + export interface ChatStreamCatchupChunksGenqlSelection{ chunks?: boolean | number maxSeq?: boolean | number + error?: ChatStreamErrorGenqlSelection __typename?: boolean | number __scalar?: boolean | number } @@ -6071,6 +6087,7 @@ export interface MutationGenqlSelection{ updateCalendarChannel?: (CalendarChannelGenqlSelection & { __args: {input: UpdateCalendarChannelInput} }) createChatThread?: AgentChatThreadGenqlSelection sendChatMessage?: (SendChatMessageResultGenqlSelection & { __args: {threadId: Scalars['UUID'], text: Scalars['String'], messageId: Scalars['UUID'], browsingContext?: (Scalars['JSON'] | null), modelId?: (Scalars['String'] | null), fileAttachments?: (FileAttachmentInput[] | null)} }) + retryChatMessage?: (SendChatMessageResultGenqlSelection & { __args: {threadId: Scalars['UUID'], modelId?: (Scalars['String'] | null)} }) stopAgentChatStream?: { __args: {threadId: Scalars['UUID']} } renameChatThread?: (AgentChatThreadGenqlSelection & { __args: {id: Scalars['UUID'], title: Scalars['String']} }) archiveChatThread?: (AgentChatThreadGenqlSelection & { __args: {id: Scalars['UUID']} }) @@ -8452,6 +8469,14 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null + const ChatStreamError_possibleTypes: string[] = ['ChatStreamError'] + export const isChatStreamError = (obj?: { __typename?: any } | null): obj is ChatStreamError => { + if (!obj?.__typename) throw new Error('__typename is missing in "isChatStreamError"') + return ChatStreamError_possibleTypes.includes(obj.__typename) + } + + + const ChatStreamCatchupChunks_possibleTypes: string[] = ['ChatStreamCatchupChunks'] export const isChatStreamCatchupChunks = (obj?: { __typename?: any } | null): obj is ChatStreamCatchupChunks => { if (!obj?.__typename) throw new Error('__typename is missing in "isChatStreamCatchupChunks"') diff --git a/packages/twenty-client-sdk/src/metadata/generated/types.ts b/packages/twenty-client-sdk/src/metadata/generated/types.ts index 78dffd2ab4..3dbd67db62 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/types.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/types.ts @@ -71,18 +71,18 @@ export default { 276, 277, 284, - 323, 324, 325, 326, - 328, - 330, - 341, - 348, - 355, - 438, - 483, - 492 + 327, + 329, + 331, + 342, + 349, + 356, + 439, + 484, + 493 ], "types": { "BillingProductDTO": { @@ -5656,6 +5656,17 @@ export default { 1 ] }, + "ChatStreamError": { + "code": [ + 1 + ], + "message": [ + 1 + ], + "__typename": [ + 1 + ] + }, "ChatStreamCatchupChunks": { "chunks": [ 15 @@ -5663,6 +5674,9 @@ export default { "maxSeq": [ 21 ], + "error": [ + 316 + ], "__typename": [ 1 ] @@ -5723,7 +5737,7 @@ export default { 3 ], "evaluations": [ - 319 + 320 ], "messages": [ 312 @@ -5757,19 +5771,19 @@ export default { 1 ], "syncStatus": [ - 323 - ], - "syncStage": [ 324 ], - "visibility": [ + "syncStage": [ 325 ], + "visibility": [ + 326 + ], "isContactAutoCreationEnabled": [ 6 ], "contactAutoCreationPolicy": [ - 326 + 327 ], "isSyncEnabled": [ 6 @@ -5820,7 +5834,7 @@ export default { 1 ], "pendingSyncAction": [ - 328 + 329 ], "messageChannelId": [ 3 @@ -5838,7 +5852,7 @@ export default { "MessageFolderPendingSyncAction": {}, "CollectionHash": { "collectionName": [ - 330 + 331 ], "hash": [ 1 @@ -5902,13 +5916,13 @@ export default { }, "MinimalMetadata": { "objectMetadataItems": [ - 331 - ], - "views": [ 332 ], + "views": [ + 333 + ], "collectionHashes": [ - 329 + 330 ], "__typename": [ 1 @@ -6061,7 +6075,7 @@ export default { 2, { "input": [ - 335, + 336, "GetApiKeyInput!" ] } @@ -6164,7 +6178,7 @@ export default { 25, { "input": [ - 336, + 337, "AgentIdInput!" ] } @@ -6220,7 +6234,7 @@ export default { 41, { "input": [ - 337, + 338, "LogicFunctionIdInput!" ] } @@ -6232,7 +6246,7 @@ export default { 15, { "input": [ - 337, + 338, "LogicFunctionIdInput!" ] } @@ -6241,7 +6255,7 @@ export default { 1, { "input": [ - 337, + 338, "LogicFunctionIdInput!" ] } @@ -6407,7 +6421,7 @@ export default { 279, { "input": [ - 338, + 339, "PreviewMessageCampaignAudienceInput!" ] } @@ -6457,7 +6471,7 @@ export default { } ], "myMessageFolders": [ - 327, + 328, { "messageChannelId": [ 3 @@ -6465,7 +6479,7 @@ export default { } ], "myCalendarChannels": [ - 322, + 323, { "connectedAccountId": [ 3 @@ -6473,13 +6487,13 @@ export default { } ], "minimalMetadata": [ - 333 + 334 ], "appConnections": [ 214, { "filter": [ - 339 + 340 ] } ], @@ -6493,7 +6507,7 @@ export default { } ], "findWorkspaceAiStats": [ - 321 + 322 ], "chatThreads": [ 313 @@ -6517,7 +6531,7 @@ export default { } ], "chatStreamCatchupChunks": [ - 316, + 317, { "threadId": [ 3, @@ -6541,7 +6555,7 @@ export default { } ], "agentTurns": [ - 320, + 321, { "agentId": [ 3, @@ -6610,7 +6624,7 @@ export default { 310, { "input": [ - 340, + 341, "EventLogQueryInput!" ] } @@ -6619,7 +6633,7 @@ export default { 304, { "input": [ - 344, + 345, "PieChartDataInput!" ] } @@ -6628,7 +6642,7 @@ export default { 302, { "input": [ - 345, + 346, "LineChartDataInput!" ] } @@ -6637,7 +6651,7 @@ export default { 299, { "input": [ - 346, + 347, "BarChartDataInput!" ] } @@ -6687,7 +6701,7 @@ export default { 260, { "input": [ - 347 + 348 ] } ], @@ -6761,10 +6775,10 @@ export default { }, "EventLogQueryInput": { "table": [ - 341 + 342 ], "filters": [ - 342 + 343 ], "first": [ 21 @@ -6785,7 +6799,7 @@ export default { 1 ], "dateRange": [ - 343 + 344 ], "recordId": [ 1 @@ -6852,7 +6866,7 @@ export default { 1 ], "operationTypes": [ - 348 + 349 ], "__typename": [ 1 @@ -6864,7 +6878,7 @@ export default { 6, { "input": [ - 350, + 351, "AddQuerySubscriptionInput!" ] } @@ -6873,7 +6887,7 @@ export default { 6, { "input": [ - 351, + 352, "RemoveQueryFromEventStreamInput!" ] } @@ -6882,7 +6896,7 @@ export default { 156, { "inputs": [ - 352, + 353, "[CreateNavigationMenuItemInput!]!" ] } @@ -6891,7 +6905,7 @@ export default { 156, { "input": [ - 352, + 353, "CreateNavigationMenuItemInput!" ] } @@ -6900,7 +6914,7 @@ export default { 156, { "inputs": [ - 353, + 354, "[UpdateOneNavigationMenuItemInput!]!" ] } @@ -6909,7 +6923,7 @@ export default { 156, { "input": [ - 353, + 354, "UpdateOneNavigationMenuItemInput!" ] } @@ -6936,7 +6950,7 @@ export default { 127, { "file": [ - 355, + 356, "Upload!" ] } @@ -6957,7 +6971,7 @@ export default { 127, { "file": [ - 355, + 356, "Upload!" ] } @@ -6966,7 +6980,7 @@ export default { 127, { "file": [ - 355, + 356, "Upload!" ] } @@ -6975,7 +6989,7 @@ export default { 127, { "file": [ - 355, + 356, "Upload!" ] } @@ -6984,7 +6998,7 @@ export default { 127, { "file": [ - 355, + 356, "Upload!" ] } @@ -6993,7 +7007,7 @@ export default { 127, { "file": [ - 355, + 356, "Upload!" ], "fieldMetadataId": [ @@ -7006,7 +7020,7 @@ export default { 127, { "file": [ - 355, + 356, "Upload!" ], "fieldMetadataUniversalIdentifier": [ @@ -7019,7 +7033,7 @@ export default { 58, { "input": [ - 356, + 357, "CreateViewFilterGroupInput!" ] } @@ -7032,7 +7046,7 @@ export default { "String!" ], "input": [ - 357, + 358, "UpdateViewFilterGroupInput!" ] } @@ -7059,7 +7073,7 @@ export default { 60, { "input": [ - 358, + 359, "CreateViewFilterInput!" ] } @@ -7068,7 +7082,7 @@ export default { 60, { "input": [ - 359, + 360, "UpdateViewFilterInput!" ] } @@ -7077,7 +7091,7 @@ export default { 60, { "input": [ - 361, + 362, "DeleteViewFilterInput!" ] } @@ -7086,7 +7100,7 @@ export default { 60, { "input": [ - 362, + 363, "DestroyViewFilterInput!" ] } @@ -7095,7 +7109,7 @@ export default { 66, { "input": [ - 363, + 364, "CreateViewInput!" ] } @@ -7108,7 +7122,7 @@ export default { "String!" ], "input": [ - 364, + 365, "UpdateViewInput!" ] } @@ -7135,7 +7149,7 @@ export default { 66, { "input": [ - 365, + 366, "UpsertViewWidgetInput!" ] } @@ -7144,7 +7158,7 @@ export default { 63, { "input": [ - 370, + 371, "CreateViewSortInput!" ] } @@ -7153,7 +7167,7 @@ export default { 63, { "input": [ - 371, + 372, "UpdateViewSortInput!" ] } @@ -7162,7 +7176,7 @@ export default { 6, { "input": [ - 373, + 374, "DeleteViewSortInput!" ] } @@ -7171,7 +7185,7 @@ export default { 6, { "input": [ - 374, + 375, "DestroyViewSortInput!" ] } @@ -7180,7 +7194,7 @@ export default { 56, { "input": [ - 375, + 376, "UpdateViewFieldInput!" ] } @@ -7189,7 +7203,7 @@ export default { 56, { "input": [ - 377, + 378, "CreateViewFieldInput!" ] } @@ -7198,7 +7212,7 @@ export default { 56, { "inputs": [ - 377, + 378, "[CreateViewFieldInput!]!" ] } @@ -7207,7 +7221,7 @@ export default { 56, { "input": [ - 378, + 379, "DeleteViewFieldInput!" ] } @@ -7216,7 +7230,7 @@ export default { 56, { "input": [ - 379, + 380, "DestroyViewFieldInput!" ] } @@ -7225,7 +7239,7 @@ export default { 65, { "input": [ - 380, + 381, "UpdateViewFieldGroupInput!" ] } @@ -7234,7 +7248,7 @@ export default { 65, { "input": [ - 382, + 383, "CreateViewFieldGroupInput!" ] } @@ -7243,7 +7257,7 @@ export default { 65, { "inputs": [ - 382, + 383, "[CreateViewFieldGroupInput!]!" ] } @@ -7252,7 +7266,7 @@ export default { 65, { "input": [ - 383, + 384, "DeleteViewFieldGroupInput!" ] } @@ -7261,7 +7275,7 @@ export default { 65, { "input": [ - 384, + 385, "DestroyViewFieldGroupInput!" ] } @@ -7270,7 +7284,7 @@ export default { 66, { "input": [ - 385, + 386, "UpsertFieldsWidgetInput!" ] } @@ -7279,7 +7293,7 @@ export default { 2, { "input": [ - 388, + 389, "CreateApiKeyInput!" ] } @@ -7288,7 +7302,7 @@ export default { 2, { "input": [ - 389, + 390, "UpdateApiKeyInput!" ] } @@ -7297,7 +7311,7 @@ export default { 2, { "input": [ - 390, + 391, "RevokeApiKeyInput!" ] } @@ -7455,7 +7469,7 @@ export default { 126, { "input": [ - 391, + 392, "CreateApprovedAccessDomainInput!" ] } @@ -7464,7 +7478,7 @@ export default { 6, { "input": [ - 392, + 393, "DeleteApprovedAccessDomainInput!" ] } @@ -7473,7 +7487,7 @@ export default { 126, { "input": [ - 393, + 394, "ValidateApprovedAccessDomainInput!" ] } @@ -7482,7 +7496,7 @@ export default { 119, { "input": [ - 394, + 395, "CreatePageLayoutTabInput!" ] } @@ -7495,7 +7509,7 @@ export default { "String!" ], "input": [ - 395, + 396, "UpdatePageLayoutTabInput!" ] } @@ -7513,7 +7527,7 @@ export default { 120, { "input": [ - 396, + 397, "CreatePageLayoutInput!" ] } @@ -7526,7 +7540,7 @@ export default { "String!" ], "input": [ - 397, + 398, "UpdatePageLayoutInput!" ] } @@ -7548,7 +7562,7 @@ export default { "String!" ], "input": [ - 398, + 399, "UpdatePageLayoutWithTabsInput!" ] } @@ -7584,7 +7598,7 @@ export default { 81, { "input": [ - 402, + 403, "CreatePageLayoutWidgetInput!" ] } @@ -7597,7 +7611,7 @@ export default { "String!" ], "input": [ - 403, + 404, "UpdatePageLayoutWidgetInput!" ] } @@ -7615,7 +7629,7 @@ export default { 25, { "input": [ - 404, + 405, "CreateAgentInput!" ] } @@ -7624,7 +7638,7 @@ export default { 25, { "input": [ - 405, + 406, "UpdateAgentInput!" ] } @@ -7633,7 +7647,7 @@ export default { 25, { "input": [ - 336, + 337, "AgentIdInput!" ] } @@ -7642,7 +7656,7 @@ export default { 52, { "input": [ - 406, + 407, "CreateOneObjectInput!" ] } @@ -7651,7 +7665,7 @@ export default { 52, { "input": [ - 408, + 409, "DeleteOneObjectInput!" ] } @@ -7660,7 +7674,7 @@ export default { 52, { "input": [ - 409, + 410, "UpdateOneObjectInput!" ] } @@ -7669,7 +7683,7 @@ export default { 45, { "input": [ - 411, + 412, "CreateOneIndexInput!" ] } @@ -7678,7 +7692,7 @@ export default { 45, { "input": [ - 414, + 415, "DeleteOneIndexInput!" ] } @@ -7687,7 +7701,7 @@ export default { 41, { "input": [ - 337, + 338, "LogicFunctionIdInput!" ] } @@ -7696,7 +7710,7 @@ export default { 41, { "input": [ - 415, + 416, "CreateLogicFunctionFromSourceInput!" ] } @@ -7705,7 +7719,7 @@ export default { 165, { "input": [ - 416, + 417, "ExecuteOneLogicFunctionInput!" ] } @@ -7714,7 +7728,7 @@ export default { 6, { "input": [ - 417, + 418, "UpdateLogicFunctionFromSourceInput!" ] } @@ -7723,7 +7737,7 @@ export default { 35, { "input": [ - 419, + 420, "CreateCommandMenuItemInput!" ] } @@ -7732,7 +7746,7 @@ export default { 35, { "input": [ - 420, + 421, "UpdateCommandMenuItemInput!" ] } @@ -7759,7 +7773,7 @@ export default { 34, { "input": [ - 421, + 422, "CreateFrontComponentInput!" ] } @@ -7768,7 +7782,7 @@ export default { 34, { "input": [ - 422, + 423, "UpdateFrontComponentInput!" ] } @@ -7786,7 +7800,7 @@ export default { 72, { "data": [ - 424, + 425, "ActivateWorkspaceInput!" ] } @@ -7795,7 +7809,7 @@ export default { 72, { "data": [ - 425, + 426, "UpdateWorkspaceInput!" ] } @@ -7810,7 +7824,7 @@ export default { 43, { "input": [ - 426, + 427, "CreateOneFieldMetadataInput!" ] } @@ -7819,7 +7833,7 @@ export default { 43, { "input": [ - 428, + 429, "UpdateOneFieldMetadataInput!" ] } @@ -7828,7 +7842,7 @@ export default { 43, { "input": [ - 430, + 431, "DeleteOneFieldInput!" ] } @@ -7837,7 +7851,7 @@ export default { 62, { "input": [ - 431, + 432, "CreateViewGroupInput!" ] } @@ -7846,7 +7860,7 @@ export default { 62, { "inputs": [ - 431, + 432, "[CreateViewGroupInput!]!" ] } @@ -7855,7 +7869,7 @@ export default { 62, { "input": [ - 432, + 433, "UpdateViewGroupInput!" ] } @@ -7864,7 +7878,7 @@ export default { 62, { "inputs": [ - 432, + 433, "[UpdateViewGroupInput!]!" ] } @@ -7873,7 +7887,7 @@ export default { 62, { "input": [ - 434, + 435, "DeleteViewGroupInput!" ] } @@ -7882,7 +7896,7 @@ export default { 62, { "input": [ - 435, + 436, "DestroyViewGroupInput!" ] } @@ -7891,7 +7905,7 @@ export default { 6, { "workspaceMigration": [ - 436, + 437, "WorkspaceMigrationInput!" ] } @@ -7922,7 +7936,7 @@ export default { 29, { "createRoleInput": [ - 439, + 440, "CreateRoleInput!" ] } @@ -7931,7 +7945,7 @@ export default { 29, { "updateRoleInput": [ - 440, + 441, "UpdateRoleInput!" ] } @@ -7949,7 +7963,7 @@ export default { 16, { "upsertObjectPermissionsInput": [ - 442, + 443, "UpsertObjectPermissionsInput!" ] } @@ -7958,7 +7972,7 @@ export default { 27, { "upsertPermissionFlagsInput": [ - 444, + 445, "UpsertPermissionFlagsInput!" ] } @@ -7967,7 +7981,7 @@ export default { 26, { "upsertFieldPermissionsInput": [ - 445, + 446, "UpsertFieldPermissionsInput!" ] } @@ -7976,7 +7990,7 @@ export default { 230, { "input": [ - 447, + 448, "UpsertRowLevelPermissionPredicatesInput!" ] } @@ -8007,7 +8021,7 @@ export default { 196, { "input": [ - 450, + 451, "CreateApplicationRegistrationInput!" ] } @@ -8016,7 +8030,7 @@ export default { 7, { "input": [ - 451, + 452, "UpdateApplicationRegistrationInput!" ] } @@ -8043,7 +8057,7 @@ export default { 5, { "input": [ - 453, + 454, "CreateApplicationRegistrationVariableInput!" ] } @@ -8052,7 +8066,7 @@ export default { 5, { "input": [ - 454, + 455, "UpdateApplicationRegistrationVariableInput!" ] } @@ -8070,7 +8084,7 @@ export default { 7, { "file": [ - 355, + 356, "Upload!" ], "universalIdentifier": [ @@ -8095,7 +8109,7 @@ export default { 280, { "input": [ - 456, + 457, "SendEmailViaDomainInput!" ] } @@ -8104,7 +8118,7 @@ export default { 282, { "input": [ - 457, + 458, "SendMessageCampaignInput!" ] } @@ -8113,7 +8127,7 @@ export default { 283, { "input": [ - 458, + 459, "CreateUnsubscribeTopicInput!" ] } @@ -8122,7 +8136,7 @@ export default { 283, { "input": [ - 459, + 460, "UpdateUnsubscribeTopicInput!" ] } @@ -8140,7 +8154,7 @@ export default { 270, { "input": [ - 460, + 461, "UpdateMessageChannelInput!" ] } @@ -8149,7 +8163,7 @@ export default { 278, { "input": [ - 462, + 463, "CreateEmailGroupChannelInput!" ] } @@ -8167,7 +8181,7 @@ export default { 268, { "input": [ - 463, + 464, "CreateEmailingDomainInput!" ] } @@ -8203,7 +8217,7 @@ export default { 295, { "input": [ - 464, + 465, "RunAgentInput!" ] } @@ -8212,7 +8226,7 @@ export default { 292, { "input": [ - 465, + 466, "CreateWebhookInput!" ] } @@ -8221,7 +8235,7 @@ export default { 292, { "input": [ - 466, + 467, "UpdateWebhookInput!" ] } @@ -8236,28 +8250,28 @@ export default { } ], "updateMessageFolder": [ - 327, + 328, { "input": [ - 468, + 469, "UpdateMessageFolderInput!" ] } ], "updateMessageFolders": [ - 327, + 328, { "input": [ - 470, + 471, "UpdateMessageFoldersInput!" ] } ], "updateCalendarChannel": [ - 322, + 323, { "input": [ - 471, + 472, "UpdateCalendarChannelInput!" ] } @@ -8266,7 +8280,7 @@ export default { 313 ], "sendChatMessage": [ - 317, + 318, { "threadId": [ 3, @@ -8287,11 +8301,23 @@ export default { 1 ], "fileAttachments": [ - 473, + 474, "[FileAttachmentInput!]" ] } ], + "retryChatMessage": [ + 318, + { + "threadId": [ + 3, + "UUID!" + ], + "modelId": [ + 1 + ] + } + ], "stopAgentChatStream": [ 6, { @@ -8354,7 +8380,7 @@ export default { 311, { "input": [ - 474, + 475, "CreateSkillInput!" ] } @@ -8363,7 +8389,7 @@ export default { 311, { "input": [ - 475, + 476, "UpdateSkillInput!" ] } @@ -8396,7 +8422,7 @@ export default { } ], "evaluateAgentTurn": [ - 319, + 320, { "turnId": [ 3, @@ -8405,7 +8431,7 @@ export default { } ], "runEvaluationInput": [ - 320, + 321, { "agentId": [ 3, @@ -8421,7 +8447,7 @@ export default { 243, { "input": [ - 476, + 477, "GetAuthorizationUrlForSSOInput!" ] } @@ -8587,7 +8613,7 @@ export default { 246, { "input": [ - 477 + 478 ] } ], @@ -8599,7 +8625,7 @@ export default { "String!" ], "file": [ - 355, + 356, "Upload!" ] } @@ -8742,7 +8768,7 @@ export default { 6, { "input": [ - 478, + 479, "UpdateWorkspaceMemberSettingsInput!" ] } @@ -8776,7 +8802,7 @@ export default { 221, { "input": [ - 479, + 480, "SetupOIDCSsoInput!" ] } @@ -8785,7 +8811,7 @@ export default { 221, { "input": [ - 480, + 481, "SetupSAMLSsoInput!" ] } @@ -8794,7 +8820,7 @@ export default { 217, { "input": [ - 481, + 482, "DeleteSsoInput!" ] } @@ -8803,7 +8829,7 @@ export default { 218, { "input": [ - 482, + 483, "EditSsoInput!" ] } @@ -8832,7 +8858,7 @@ export default { 307, { "type": [ - 483, + 484, "AnalyticsType!" ], "name": [ @@ -8872,7 +8898,7 @@ export default { 297, { "input": [ - 484, + 485, "CreateCalendarEventInput!" ] } @@ -8881,7 +8907,7 @@ export default { 306, { "input": [ - 485, + 486, "SendEmailInput!" ] } @@ -8903,7 +8929,7 @@ export default { "String!" ], "connectionParameters": [ - 487, + 488, "EmailAccountConnectionParameters!" ], "id": [ @@ -8915,7 +8941,7 @@ export default { 167, { "input": [ - 489, + 490, "UpdateLabPublicFeatureFlagInput!" ] } @@ -8955,7 +8981,7 @@ export default { 74, { "input": [ - 490, + 491, "CreateOneAppTokenInput!" ] } @@ -9025,7 +9051,7 @@ export default { 263, { "file": [ - 355, + 356, "Upload!" ], "applicationUniversalIdentifier": [ @@ -9033,7 +9059,7 @@ export default { "String!" ], "fileFolder": [ - 492, + 493, "FileFolder!" ], "filePath": [ @@ -9142,7 +9168,7 @@ export default { 3 ], "update": [ - 354 + 355 ], "__typename": [ 1 @@ -9252,7 +9278,7 @@ export default { 3 ], "update": [ - 360 + 361 ], "__typename": [ 1 @@ -9417,17 +9443,17 @@ export default { 3 ], "viewFields": [ - 366 - ], - "viewFilters": [ 367 ], - "viewFilterGroups": [ + "viewFilters": [ 368 ], - "viewSorts": [ + "viewFilterGroups": [ 369 ], + "viewSorts": [ + 370 + ], "__typename": [ 1 ] @@ -9537,7 +9563,7 @@ export default { 3 ], "update": [ - 372 + 373 ], "__typename": [ 1 @@ -9575,7 +9601,7 @@ export default { 3 ], "update": [ - 376 + 377 ], "__typename": [ 1 @@ -9651,7 +9677,7 @@ export default { 3 ], "update": [ - 381 + 382 ], "__typename": [ 1 @@ -9715,10 +9741,10 @@ export default { 3 ], "groups": [ - 386 + 387 ], "fields": [ - 387 + 388 ], "__typename": [ 1 @@ -9738,7 +9764,7 @@ export default { 6 ], "fields": [ - 387 + 388 ], "__typename": [ 1 @@ -9906,7 +9932,7 @@ export default { 3 ], "tabs": [ - 399 + 400 ], "__typename": [ 1 @@ -9929,7 +9955,7 @@ export default { 85 ], "widgets": [ - 400 + 401 ], "__typename": [ 1 @@ -9952,7 +9978,7 @@ export default { 3 ], "gridPosition": [ - 401 + 402 ], "position": [ 15 @@ -10001,7 +10027,7 @@ export default { 3 ], "gridPosition": [ - 401 + 402 ], "position": [ 15 @@ -10027,7 +10053,7 @@ export default { 3 ], "gridPosition": [ - 401 + 402 ], "position": [ 15 @@ -10120,7 +10146,7 @@ export default { }, "CreateOneObjectInput": { "object": [ - 407 + 408 ], "__typename": [ 1 @@ -10180,7 +10206,7 @@ export default { }, "UpdateOneObjectInput": { "update": [ - 410 + 411 ], "id": [ 3 @@ -10235,7 +10261,7 @@ export default { }, "CreateOneIndexInput": { "index": [ - 412 + 413 ], "__typename": [ 1 @@ -10246,7 +10272,7 @@ export default { 3 ], "fields": [ - 413 + 414 ], "indexType": [ 46 @@ -10331,7 +10357,7 @@ export default { 3 ], "update": [ - 418 + 419 ], "__typename": [ 1 @@ -10491,7 +10517,7 @@ export default { 3 ], "update": [ - 423 + 424 ], "__typename": [ 1 @@ -10595,7 +10621,7 @@ export default { }, "CreateOneFieldMetadataInput": { "field": [ - 427 + 428 ], "__typename": [ 1 @@ -10668,7 +10694,7 @@ export default { 3 ], "update": [ - 429 + 430 ], "__typename": [ 1 @@ -10763,7 +10789,7 @@ export default { 3 ], "update": [ - 433 + 434 ], "__typename": [ 1 @@ -10804,7 +10830,7 @@ export default { }, "WorkspaceMigrationInput": { "actions": [ - 437 + 438 ], "__typename": [ 1 @@ -10812,10 +10838,10 @@ export default { }, "WorkspaceMigrationDeleteActionInput": { "type": [ - 438 + 439 ], "metadataName": [ - 330 + 331 ], "universalIdentifier": [ 1 @@ -10871,7 +10897,7 @@ export default { }, "UpdateRoleInput": { "update": [ - 441 + 442 ], "id": [ 3 @@ -10926,7 +10952,7 @@ export default { 3 ], "objectPermissions": [ - 443 + 444 ], "__typename": [ 1 @@ -10968,7 +10994,7 @@ export default { 3 ], "fieldPermissions": [ - 446 + 447 ], "__typename": [ 1 @@ -10999,10 +11025,10 @@ export default { 3 ], "predicates": [ - 448 + 449 ], "predicateGroups": [ - 449 + 450 ], "__typename": [ 1 @@ -11082,7 +11108,7 @@ export default { 1 ], "update": [ - 452 + 453 ], "__typename": [ 1 @@ -11133,7 +11159,7 @@ export default { 1 ], "update": [ - 455 + 456 ], "__typename": [ 1 @@ -11241,7 +11267,7 @@ export default { 3 ], "update": [ - 461 + 462 ], "__typename": [ 1 @@ -11325,7 +11351,7 @@ export default { 3 ], "update": [ - 467 + 468 ], "__typename": [ 1 @@ -11353,7 +11379,7 @@ export default { 3 ], "update": [ - 469 + 470 ], "__typename": [ 1 @@ -11372,7 +11398,7 @@ export default { 3 ], "update": [ - 469 + 470 ], "__typename": [ 1 @@ -11383,7 +11409,7 @@ export default { 3 ], "update": [ - 472 + 473 ], "__typename": [ 1 @@ -11391,13 +11417,13 @@ export default { }, "UpdateCalendarChannelInputUpdates": { "visibility": [ - 325 + 326 ], "isContactAutoCreationEnabled": [ 6 ], "contactAutoCreationPolicy": [ - 326 + 327 ], "isSyncEnabled": [ 6 @@ -11623,7 +11649,7 @@ export default { 1 ], "files": [ - 486 + 487 ], "__typename": [ 1 @@ -11642,13 +11668,13 @@ export default { }, "EmailAccountConnectionParameters": { "IMAP": [ - 488 + 489 ], "SMTP": [ - 488 + 489 ], "CALDAV": [ - 488 + 489 ], "__typename": [ 1 @@ -11687,7 +11713,7 @@ export default { }, "CreateOneAppTokenInput": { "appToken": [ - 491 + 492 ], "__typename": [ 1 @@ -11716,13 +11742,13 @@ export default { 231, { "input": [ - 494, + 495, "LogicFunctionLogsInput!" ] } ], "onAgentChatEvent": [ - 318, + 319, { "threadId": [ 3, @@ -11734,7 +11760,7 @@ export default { 308, { "table": [ - 341, + 342, "EventLogTable!" ] } diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index b7f30c58a3..2a870825e2 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -862,9 +862,16 @@ export enum ChartNumberFormat { export type ChatStreamCatchupChunks = { __typename?: 'ChatStreamCatchupChunks'; chunks: Array; + error?: Maybe; maxSeq: Scalars['Int']['output']; }; +export type ChatStreamError = { + __typename?: 'ChatStreamError'; + code: Scalars['String']['output']; + message: Scalars['String']['output']; +}; + export type CheckUserExist = { __typename?: 'CheckUserExist'; availableWorkspacesCount: Scalars['Float']['output']; @@ -2577,6 +2584,7 @@ export type Mutation = { resetPageLayoutTabToDefault: PageLayoutTab; resetPageLayoutToDefault: PageLayout; resetPageLayoutWidgetToDefault: PageLayoutWidget; + retryChatMessage: SendChatMessageResult; revokeApiKey?: Maybe; rotateApplicationRegistrationClientSecret: RotateClientSecret; runAgent: RunAgentResult; @@ -3300,6 +3308,12 @@ export type MutationResetPageLayoutWidgetToDefaultArgs = { }; +export type MutationRetryChatMessageArgs = { + modelId?: InputMaybe; + threadId: Scalars['UUID']['input']; +}; + + export type MutationRevokeApiKeyArgs = { input: RevokeApiKeyInput; }; @@ -6450,6 +6464,14 @@ export type RenameChatThreadMutationVariables = Exact<{ export type RenameChatThreadMutation = { __typename?: 'Mutation', renameChatThread: { __typename?: 'AgentChatThread', id: string, title?: string | null, updatedAt: string } }; +export type RetryChatMessageMutationVariables = Exact<{ + threadId: Scalars['UUID']['input']; + modelId?: InputMaybe; +}>; + + +export type RetryChatMessageMutation = { __typename?: 'Mutation', retryChatMessage: { __typename?: 'SendChatMessageResult', messageId: string, queued: boolean, streamId?: string | null } }; + export type RunEvaluationInputMutationVariables = Exact<{ agentId: Scalars['UUID']['input']; input: Scalars['String']['input']; @@ -6546,7 +6568,7 @@ export type GetChatMessagesQueryVariables = Exact<{ }>; -export type GetChatMessagesQuery = { __typename?: 'Query', chatMessages: Array<{ __typename?: 'AgentMessage', id: string, threadId: string, turnId?: string | null, role: string, status: string, createdAt: string, parts: Array<{ __typename?: 'AgentMessagePart', id: string, messageId: string, orderIndex: number, type: string, textContent?: string | null, reasoningContent?: string | null, toolName?: string | null, toolCallId?: string | null, toolInput?: any | null, toolOutput?: any | null, state?: string | null, providerExecuted?: boolean | null, errorMessage?: string | null, errorDetails?: any | null, sourceUrlSourceId?: string | null, sourceUrlUrl?: string | null, sourceUrlTitle?: string | null, sourceDocumentSourceId?: string | null, sourceDocumentMediaType?: string | null, sourceDocumentTitle?: string | null, sourceDocumentFilename?: string | null, fileMediaType?: string | null, fileFilename?: string | null, fileUrl?: string | null, fileId?: string | null, providerMetadata?: any | null, createdAt: string }> }>, chatStreamCatchupChunks: { __typename?: 'ChatStreamCatchupChunks', chunks: Array, maxSeq: number } }; +export type GetChatMessagesQuery = { __typename?: 'Query', chatMessages: Array<{ __typename?: 'AgentMessage', id: string, threadId: string, turnId?: string | null, role: string, status: string, createdAt: string, parts: Array<{ __typename?: 'AgentMessagePart', id: string, messageId: string, orderIndex: number, type: string, textContent?: string | null, reasoningContent?: string | null, toolName?: string | null, toolCallId?: string | null, toolInput?: any | null, toolOutput?: any | null, state?: string | null, providerExecuted?: boolean | null, errorMessage?: string | null, errorDetails?: any | null, sourceUrlSourceId?: string | null, sourceUrlUrl?: string | null, sourceUrlTitle?: string | null, sourceDocumentSourceId?: string | null, sourceDocumentMediaType?: string | null, sourceDocumentTitle?: string | null, sourceDocumentFilename?: string | null, fileMediaType?: string | null, fileFilename?: string | null, fileUrl?: string | null, fileId?: string | null, providerMetadata?: any | null, createdAt: string }> }>, chatStreamCatchupChunks: { __typename?: 'ChatStreamCatchupChunks', chunks: Array, maxSeq: number, error?: { __typename?: 'ChatStreamError', code: string, message: string } | null } }; export type GetChatThreadsQueryVariables = Exact<{ [key: string]: never; }>; @@ -8702,6 +8724,7 @@ export const DeleteSkillDocument = {"kind":"Document","definitions":[{"kind":"Op export const EvaluateAgentTurnDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"EvaluateAgentTurn"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"turnId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evaluateAgentTurn"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"turnId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"turnId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"turnId"}},{"kind":"Field","name":{"kind":"Name","value":"score"}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]} as unknown as DocumentNode; export const RemoveRoleFromAgentDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemoveRoleFromAgent"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"agentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeRoleFromAgent"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"agentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"agentId"}}}]}]}}]} as unknown as DocumentNode; export const RenameChatThreadDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RenameChatThread"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"title"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"renameChatThread"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}},{"kind":"Argument","name":{"kind":"Name","value":"title"},"value":{"kind":"Variable","name":{"kind":"Name","value":"title"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode; +export const RetryChatMessageDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RetryChatMessage"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"retryChatMessage"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"threadId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}}},{"kind":"Argument","name":{"kind":"Name","value":"modelId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"messageId"}},{"kind":"Field","name":{"kind":"Name","value":"queued"}},{"kind":"Field","name":{"kind":"Name","value":"streamId"}}]}}]}}]} as unknown as DocumentNode; export const RunEvaluationInputDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RunEvaluationInput"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"agentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"runEvaluationInput"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"agentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"agentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"threadId"}},{"kind":"Field","name":{"kind":"Name","value":"agentId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"evaluations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"score"}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]}}]} as unknown as DocumentNode; export const SendChatMessageDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SendChatMessage"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"text"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"messageId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"browsingContext"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"JSON"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"fileAttachments"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"FileAttachmentInput"}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"sendChatMessage"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"threadId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}}},{"kind":"Argument","name":{"kind":"Name","value":"text"},"value":{"kind":"Variable","name":{"kind":"Name","value":"text"}}},{"kind":"Argument","name":{"kind":"Name","value":"messageId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"messageId"}}},{"kind":"Argument","name":{"kind":"Name","value":"browsingContext"},"value":{"kind":"Variable","name":{"kind":"Name","value":"browsingContext"}}},{"kind":"Argument","name":{"kind":"Name","value":"modelId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}}},{"kind":"Argument","name":{"kind":"Name","value":"fileAttachments"},"value":{"kind":"Variable","name":{"kind":"Name","value":"fileAttachments"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"messageId"}},{"kind":"Field","name":{"kind":"Name","value":"queued"}},{"kind":"Field","name":{"kind":"Name","value":"streamId"}}]}}]}}]} as unknown as DocumentNode; export const StopAgentChatStreamDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"StopAgentChatStream"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stopAgentChatStream"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"threadId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}}}]}]}}]} as unknown as DocumentNode; @@ -8715,7 +8738,7 @@ export const FindOneAgentDocument = {"kind":"Document","definitions":[{"kind":"O export const FindOneSkillDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindOneSkill"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"skill"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SkillFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SkillFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Skill"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"content"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const FindWorkspaceAiStatsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindWorkspaceAiStats"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findWorkspaceAiStats"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"conversationsCount"}},{"kind":"Field","name":{"kind":"Name","value":"skillsCount"}},{"kind":"Field","name":{"kind":"Name","value":"toolsCount"}}]}}]}}]} as unknown as DocumentNode; export const GetAgentTurnsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAgentTurns"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"agentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"agentTurns"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"agentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"agentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"threadId"}},{"kind":"Field","name":{"kind":"Name","value":"agentId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"evaluations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"score"}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}},{"kind":"Field","name":{"kind":"Name","value":"messages"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"parts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"textContent"}},{"kind":"Field","name":{"kind":"Name","value":"reasoningContent"}},{"kind":"Field","name":{"kind":"Name","value":"toolName"}},{"kind":"Field","name":{"kind":"Name","value":"toolCallId"}},{"kind":"Field","name":{"kind":"Name","value":"toolInput"}},{"kind":"Field","name":{"kind":"Name","value":"toolOutput"}},{"kind":"Field","name":{"kind":"Name","value":"errorMessage"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"providerExecuted"}},{"kind":"Field","name":{"kind":"Name","value":"errorDetails"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrlSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrlUrl"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrlTitle"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentMediaType"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentTitle"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentFilename"}},{"kind":"Field","name":{"kind":"Name","value":"fileMediaType"}},{"kind":"Field","name":{"kind":"Name","value":"fileFilename"}},{"kind":"Field","name":{"kind":"Name","value":"fileUrl"}},{"kind":"Field","name":{"kind":"Name","value":"providerMetadata"}}]}}]}}]}}]}}]} as unknown as DocumentNode; -export const GetChatMessagesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetChatMessages"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"chatMessages"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"threadId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"threadId"}},{"kind":"Field","name":{"kind":"Name","value":"turnId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"parts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"messageId"}},{"kind":"Field","name":{"kind":"Name","value":"orderIndex"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"textContent"}},{"kind":"Field","name":{"kind":"Name","value":"reasoningContent"}},{"kind":"Field","name":{"kind":"Name","value":"toolName"}},{"kind":"Field","name":{"kind":"Name","value":"toolCallId"}},{"kind":"Field","name":{"kind":"Name","value":"toolInput"}},{"kind":"Field","name":{"kind":"Name","value":"toolOutput"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"providerExecuted"}},{"kind":"Field","name":{"kind":"Name","value":"errorMessage"}},{"kind":"Field","name":{"kind":"Name","value":"errorDetails"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrlSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrlUrl"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrlTitle"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentMediaType"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentTitle"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentFilename"}},{"kind":"Field","name":{"kind":"Name","value":"fileMediaType"}},{"kind":"Field","name":{"kind":"Name","value":"fileFilename"}},{"kind":"Field","name":{"kind":"Name","value":"fileUrl"}},{"kind":"Field","name":{"kind":"Name","value":"fileId"}},{"kind":"Field","name":{"kind":"Name","value":"providerMetadata"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"chatStreamCatchupChunks"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"threadId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"chunks"}},{"kind":"Field","name":{"kind":"Name","value":"maxSeq"}}]}}]}}]} as unknown as DocumentNode; +export const GetChatMessagesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetChatMessages"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"chatMessages"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"threadId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"threadId"}},{"kind":"Field","name":{"kind":"Name","value":"turnId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"parts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"messageId"}},{"kind":"Field","name":{"kind":"Name","value":"orderIndex"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"textContent"}},{"kind":"Field","name":{"kind":"Name","value":"reasoningContent"}},{"kind":"Field","name":{"kind":"Name","value":"toolName"}},{"kind":"Field","name":{"kind":"Name","value":"toolCallId"}},{"kind":"Field","name":{"kind":"Name","value":"toolInput"}},{"kind":"Field","name":{"kind":"Name","value":"toolOutput"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"providerExecuted"}},{"kind":"Field","name":{"kind":"Name","value":"errorMessage"}},{"kind":"Field","name":{"kind":"Name","value":"errorDetails"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrlSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrlUrl"}},{"kind":"Field","name":{"kind":"Name","value":"sourceUrlTitle"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentMediaType"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentTitle"}},{"kind":"Field","name":{"kind":"Name","value":"sourceDocumentFilename"}},{"kind":"Field","name":{"kind":"Name","value":"fileMediaType"}},{"kind":"Field","name":{"kind":"Name","value":"fileFilename"}},{"kind":"Field","name":{"kind":"Name","value":"fileUrl"}},{"kind":"Field","name":{"kind":"Name","value":"fileId"}},{"kind":"Field","name":{"kind":"Name","value":"providerMetadata"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"chatStreamCatchupChunks"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"threadId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"chunks"}},{"kind":"Field","name":{"kind":"Name","value":"maxSeq"}},{"kind":"Field","name":{"kind":"Name","value":"error"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]} as unknown as DocumentNode; export const GetChatThreadsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetChatThreads"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"chatThreads"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"totalInputTokens"}},{"kind":"Field","name":{"kind":"Name","value":"totalOutputTokens"}},{"kind":"Field","name":{"kind":"Name","value":"contextWindowTokens"}},{"kind":"Field","name":{"kind":"Name","value":"conversationSize"}},{"kind":"Field","name":{"kind":"Name","value":"totalInputCredits"}},{"kind":"Field","name":{"kind":"Name","value":"totalOutputCredits"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}},{"kind":"Field","name":{"kind":"Name","value":"lastMessageAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode; export const GetToolIndexDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetToolIndex"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getToolIndex"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"objectName"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}}]}}]}}]} as unknown as DocumentNode; export const GetToolInputSchemaDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetToolInputSchema"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"toolName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getToolInputSchema"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"toolName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"toolName"}}}]}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/modules/ai/components/AgentChatMessagesFetchEffect.tsx b/packages/twenty-front/src/modules/ai/components/AgentChatMessagesFetchEffect.tsx index a21fa8351d..a622d5bbdc 100644 --- a/packages/twenty-front/src/modules/ai/components/AgentChatMessagesFetchEffect.tsx +++ b/packages/twenty-front/src/modules/ai/components/AgentChatMessagesFetchEffect.tsx @@ -14,6 +14,7 @@ import { agentChatQueuedMessagesComponentFamilyState } from '@/ai/states/agentCh import { currentAiChatThreadState } from '@/ai/states/currentAiChatThreadState'; import { skipMessagesSkeletonUntilLoadedState } from '@/ai/states/skipMessagesSkeletonUntilLoadedState'; import { mapDBMessagesToUIMessages } from '@/ai/utils/mapDBMessagesToUIMessages'; +import { SSE_CLIENT_RECONNECTED_EVENT_NAME } from '@/sse-db-event/constants/SseClientReconnectedEventName'; import { useQueryWithCallbacks } from '@/apollo/hooks/useQueryWithCallbacks'; import { useListenToBrowserEvent } from '@/browser-event/hooks/useListenToBrowserEvent'; import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState'; @@ -87,7 +88,7 @@ export const AgentChatMessagesFetchEffect = () => { const catchup = data.chatStreamCatchupChunks; - if (!isDefined(catchup) || catchup.chunks.length === 0) { + if (!isDefined(catchup)) { return; } @@ -122,6 +123,15 @@ export const AgentChatMessagesFetchEffect = () => { seq: chunkSeq, } as AgentChatSubscriptionEvent); } + + // Never replay a persisted error into an active live stream. + if (isDefined(catchup.error) && firstLiveSeq === null) { + handleEvent({ + type: 'stream-error', + code: catchup.error.code, + message: catchup.error.message, + } as AgentChatSubscriptionEvent); + } }, [ setAgentChatFetchedMessages, @@ -168,5 +178,11 @@ export const AgentChatMessagesFetchEffect = () => { onBrowserEvent: handleRefetchMessages, }); + // Replay events missed while the SSE connection was down. + useListenToBrowserEvent({ + eventName: SSE_CLIENT_RECONNECTED_EVENT_NAME, + onBrowserEvent: handleRefetchMessages, + }); + return null; }; diff --git a/packages/twenty-front/src/modules/ai/components/AiChatErrorMessage.tsx b/packages/twenty-front/src/modules/ai/components/AiChatErrorMessage.tsx index 8304eb9428..a9d54dc868 100644 --- a/packages/twenty-front/src/modules/ai/components/AiChatErrorMessage.tsx +++ b/packages/twenty-front/src/modules/ai/components/AiChatErrorMessage.tsx @@ -1,8 +1,10 @@ import { CombinedGraphQLErrors } from '@apollo/client/errors'; import { styled } from '@linaria/react'; import { t } from '@lingui/core/macro'; -import { IconAlertCircle } from 'twenty-ui/icon'; +import { IconAlertCircle, IconRefresh } from 'twenty-ui/icon'; +import { Button } from 'twenty-ui/input'; import { useContext } from 'react'; +import { isDefined } from 'twenty-shared/utils'; import { type AiChatError } from '@/ai/types/AiChatError'; import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants'; @@ -45,9 +47,13 @@ const StyledErrorMessage = styled.div` type AiChatErrorMessageProps = { error: AiChatError; + onRetry?: () => void; }; -export const AiChatErrorMessage = ({ error }: AiChatErrorMessageProps) => { +export const AiChatErrorMessage = ({ + error, + onRetry, +}: AiChatErrorMessageProps) => { const { theme } = useContext(ThemeContext); const errorMessage = CombinedGraphQLErrors.is(error) ? getErrorMessageFromApolloError(error) @@ -64,6 +70,15 @@ export const AiChatErrorMessage = ({ error }: AiChatErrorMessageProps) => { {errorMessage || t`An error occurred while processing your message`} + {isDefined(onRetry) && ( +