diff --git a/src/components/Agentic/IncidentsContainer/CreateIncidentChatOverlay/index.tsx b/src/components/Agentic/IncidentsContainer/CreateIncidentChatOverlay/index.tsx index 4a66222b..d8767ca9 100644 --- a/src/components/Agentic/IncidentsContainer/CreateIncidentChatOverlay/index.tsx +++ b/src/components/Agentic/IncidentsContainer/CreateIncidentChatOverlay/index.tsx @@ -1,17 +1,13 @@ -import { - fetchEventSource, - type EventSourceMessage -} from "@microsoft/fetch-event-source"; -import { useEffect, useRef, useState } from "react"; +import { useState } from "react"; import { useNavigate } from "react-router"; import { useAgenticDispatch } from "../../../../containers/Agentic/hooks"; import { useGetIncidentAgentEventsQuery, - useSendMessageToIncidentCreationChatMutation + useSendMessageToIncidentCreationChatMutation, + useStartIncidentCreationChatMutation } from "../../../../redux/services/digma"; import type { IncidentAgentEvent } from "../../../../redux/services/types"; import { setIsCreateIncidentChatOpen } from "../../../../redux/slices/incidentsSlice"; -import { isString } from "../../../../typeGuards/isString"; import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent"; import { CancelConfirmation } from "../../../common/CancelConfirmation"; import { trackingEvents } from "../../tracking"; @@ -20,7 +16,6 @@ import * as s from "./styles"; const AGENT_ID = "incident_entry"; const PROMPT_FONT_SIZE = 14; // in pixels const REFRESH_INTERVAL = 10 * 1000; // in milliseconds -const REFRESH_INTERVAL_DURING_STREAMING = 3 * 1000; // in milliseconds export const CreateIncidentChatOverlay = () => { const [incidentId, setIncidentId] = useState(); @@ -28,14 +23,15 @@ export const CreateIncidentChatOverlay = () => { isCloseConfirmationDialogVisible, setIsCloseConfirmationDialogVisible ] = useState(false); - const [isStartMessageSending, setIsStartMessageSending] = useState(false); - const abortControllerRef = useRef(null); const [accumulatedData, setAccumulatedData] = useState(); const navigate = useNavigate(); const dispatch = useAgenticDispatch(); + const [sendStartMessage, { isLoading: isStartMessageSending }] = + useStartIncidentCreationChatMutation(); + const [sendMessage, { isLoading: isSubsequentMessageSending }] = useSendMessageToIncidentCreationChatMutation(); @@ -48,9 +44,7 @@ export const CreateIncidentChatOverlay = () => { }, { skip: !incidentId, - pollingInterval: isMessageSending - ? REFRESH_INTERVAL_DURING_STREAMING - : REFRESH_INTERVAL + pollingInterval: REFRESH_INTERVAL } ); @@ -67,93 +61,12 @@ export const CreateIncidentChatOverlay = () => { mcp_name: null } ]); - // Stop any existing connection - if (abortControllerRef.current) { - abortControllerRef.current.abort(); - } - - abortControllerRef.current = new AbortController(); - - setIsStartMessageSending(true); - void fetchEventSource( - `${ - isString(window.digmaApiProxyPrefix) - ? window.digmaApiProxyPrefix - : "/api/" - }Agentic/incident-entry`, - { - method: "POST", - credentials: "same-origin", - headers: { - "Content-Type": "application/json" - }, - signal: abortControllerRef.current.signal, - body: JSON.stringify({ - text - }), - openWhenHidden: true, - onopen: (response: Response) => { - if (response.ok) { - setIncidentId( - response.headers.get("agentic-conversation-id") ?? "" - ); - // eslint-disable-next-line no-console - console.log( - `[${new Date().toISOString()}] Got conversation ID:`, - response.headers.get("agentic-conversation-id") ?? "" - ); - setIsStartMessageSending(false); - return Promise.resolve(); - } else { - setIsStartMessageSending(false); - return Promise.reject( - new Error(`HTTP ${response.status}: ${response.statusText}`) - ); - } - }, - onmessage: (message: EventSourceMessage) => { - // eslint-disable-next-line no-console - console.log( - `[${new Date().toISOString()}] Received message:`, - message - ); - // if (message.data) { - // try { - // const parsedData = JSON.parse( - // message.data - // ) as IncidentAgentEvent; - // if (["human", "token"].includes(parsedData.type)) { - // setAccumulatedData((prev) => - // prev ? [...prev, parsedData] : [parsedData] - // ); - // } - // if (parsedData.type === "input_user_required") { - // setIsStartMessageSending(false); - // } - // } catch (error) { - // // eslint-disable-next-line no-console - // console.error("Error parsing message data:", error); - // } - // } - }, - onerror: (err: unknown) => { - abortControllerRef.current = null; - setIsStartMessageSending(false); - let errorMessage = "Unknown error starting incident creation chat"; - if (err instanceof Error) { - errorMessage = err.message; - } - - // eslint-disable-next-line no-console - console.error(errorMessage); - throw new Error(errorMessage); // Rethrow the error to avoid retrying - }, - onclose: () => { - abortControllerRef.current = null; - } - } - ); + void sendStartMessage({ data: { text } }) + .unwrap() + .then((response) => { + setIncidentId(response.conversation_id); + }); } else { // Send subsequent messages to the incident creation chat void sendMessage({ @@ -188,14 +101,6 @@ export const CreateIncidentChatOverlay = () => { dispatch(setIsCreateIncidentChatOpen(false)); }; - useEffect(() => { - return () => { - if (abortControllerRef.current) { - abortControllerRef.current.abort(); - } - }; - }, []); - return ( <> diff --git a/src/redux/services/digma.ts b/src/redux/services/digma.ts index 1928fa95..24ec1816 100644 --- a/src/redux/services/digma.ts +++ b/src/redux/services/digma.ts @@ -110,6 +110,8 @@ import type { SetMetricsReportDataPayload, SetServiceEndpointsPayload, SetServiceEnvironmentsPayload, + StartIncidentCreationChatPayload, + StartIncidentCreationChatResponse, TestMCPServerPayload, TestMCPServerResponse, UndismissErrorPayload, @@ -663,12 +665,23 @@ export const digmaApi = createApi({ }), invalidatesTags: ["IncidentAgentChatEvent"] }), + startIncidentCreationChat: builder.mutation< + StartIncidentCreationChatResponse, + StartIncidentCreationChatPayload + >({ + query: ({ data }) => ({ + url: `Agentic/manual-incident`, + method: "POST", + body: data + }), + invalidatesTags: ["IncidentEntryAgentChatEvent"] + }), sendMessageToIncidentCreationChat: builder.mutation< - unknown, // text/event-stream + void, SendMessageToIncidentCreationChatPayload >({ query: ({ incidentId, data }) => ({ - url: `Agentic/incident-entry/${window.encodeURIComponent(incidentId)}`, + url: `Agentic/manual-incident/${window.encodeURIComponent(incidentId)}`, method: "POST", body: data }), @@ -845,6 +858,7 @@ export const { useGetIncidentAgentEventsQuery, useGetIncidentAgentChatEventsQuery, useSendMessageToIncidentAgentChatMutation, + useStartIncidentCreationChatMutation, useSendMessageToIncidentCreationChatMutation, useGetIncidentAgentDirectivesQuery, useDeleteIncidentAgentDirectiveMutation, diff --git a/src/redux/services/types.ts b/src/redux/services/types.ts index 11c58f64..dc88924a 100644 --- a/src/redux/services/types.ts +++ b/src/redux/services/types.ts @@ -1258,6 +1258,14 @@ export interface SendMessageToIncidentAgentChatPayload { data: { text: string }; } +export interface StartIncidentCreationChatPayload { + data: { text: string }; +} + +export interface StartIncidentCreationChatResponse { + conversation_id: string; +} + export interface SendMessageToIncidentCreationChatPayload { incidentId: string; data: { text: string };