Skip to content

Commit d0b93c9

Browse files
authored
[Agent Builder] persist error steps basic example (#245743)
1 parent 26575d6 commit d0b93c9

7 files changed

Lines changed: 56 additions & 33 deletions

File tree

x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_rounds/round_error/round_error.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
import React, { useState } from 'react';
9+
import type { ConversationRoundStep } from '@kbn/onechat-common';
910
import { isContextLengthExceededAgentError } from '@kbn/onechat-common';
1011
import { css } from '@emotion/react';
1112
import { i18n } from '@kbn/i18n';
@@ -14,9 +15,11 @@ import { RoundErrorThinkingTitle } from './round_error_thinking_title';
1415
import { ContextExceededRoundError } from './context_exceeded_round_error';
1516
import { GenericRoundError } from './generic_round_error';
1617
import { RoundErrorThinkingPanel } from './round_error_thinking_panel';
18+
import { RoundSteps } from '../round_thinking/steps/round_steps';
1719

1820
interface RoundErrorProps {
1921
error: unknown;
22+
errorSteps: ConversationRoundStep[];
2023
onRetry: () => void;
2124
}
2225

@@ -29,7 +32,7 @@ const labels = {
2932
}),
3033
};
3134

32-
export const RoundError: React.FC<RoundErrorProps> = ({ error, onRetry }) => {
35+
export const RoundError: React.FC<RoundErrorProps> = ({ error, errorSteps, onRetry }) => {
3336
const { euiTheme } = useEuiTheme();
3437
const [showErrorThinkingPanel, setShowErrorThinkingPanel] = useState(false);
3538

@@ -52,6 +55,7 @@ export const RoundError: React.FC<RoundErrorProps> = ({ error, onRetry }) => {
5255
>
5356
{showErrorThinkingPanel ? (
5457
<RoundErrorThinkingPanel onClose={toggleErrorThinkingPanel}>
58+
<RoundSteps isLoading={false} steps={errorSteps} />
5559
{errorContent}
5660
</RoundErrorThinkingPanel>
5761
) : (

x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_rounds/round_layout.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,21 @@ export const RoundLayout: React.FC<RoundLayoutProps> = ({
3838

3939
const { isResponseLoading, error, retry: retrySendMessage } = useSendMessage();
4040

41+
const isLoadingCurrentRound = isResponseLoading && isCurrentRound;
42+
const isErrorCurrentRound = Boolean(error) && isCurrentRound;
43+
4144
useEffect(() => {
42-
if (isCurrentRound && isResponseLoading) {
45+
// Pending rounds and error rounds should have a min-height to match the scroll container height
46+
if ((isCurrentRound && isResponseLoading) || isErrorCurrentRound) {
4347
setRoundContainerMinHeight(scrollContainerHeight);
44-
} else if (!isCurrentRound) {
48+
} else {
4549
setRoundContainerMinHeight(0);
4650
}
47-
}, [isCurrentRound, isResponseLoading, scrollContainerHeight]);
51+
}, [isCurrentRound, isResponseLoading, scrollContainerHeight, isErrorCurrentRound]);
4852

4953
const roundContainerStyles = css`
5054
${roundContainerMinHeight > 0 ? `min-height: ${roundContainerMinHeight}px;` : 'flex-grow: 0;'};
5155
`;
52-
53-
const isLoadingCurrentRound = isResponseLoading && isCurrentRound;
54-
const isErrorCurrentRound = Boolean(error) && isCurrentRound;
55-
5656
return (
5757
<EuiFlexGroup
5858
direction="column"
@@ -68,7 +68,7 @@ export const RoundLayout: React.FC<RoundLayoutProps> = ({
6868
{/* Thinking */}
6969
<EuiFlexItem grow={false}>
7070
{isErrorCurrentRound ? (
71-
<RoundError error={error} onRetry={retrySendMessage} />
71+
<RoundError error={error} errorSteps={rawRound.steps} onRetry={retrySendMessage} />
7272
) : (
7373
<RoundThinking steps={steps} isLoading={isLoadingCurrentRound} rawRound={rawRound} />
7474
)}

x-pack/platform/plugins/shared/onechat/public/application/context/send_message/send_message_context.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
*/
77

88
import React, { createContext, useContext } from 'react';
9+
import type { ConversationRoundStep } from '@kbn/onechat-common';
910
import { useSendMessageMutation } from './use_send_message_mutation';
1011
import { useConnectorSelection } from '../../hooks/chat/use_connector_selection';
1112

1213
interface SendMessageState {
1314
sendMessage: ({ message }: { message: string }) => void;
1415
isResponseLoading: boolean;
15-
error: unknown;
1616
pendingMessage: string | undefined;
17+
error: unknown;
18+
errorSteps: ConversationRoundStep[];
1719
agentReasoning: string | null;
1820
retry: () => void;
1921
canCancel: boolean;
@@ -34,8 +36,9 @@ export const SendMessageProvider = ({ children }: { children: React.ReactNode })
3436
const {
3537
sendMessage,
3638
isResponseLoading,
37-
error,
3839
pendingMessage,
40+
error,
41+
errorSteps,
3942
agentReasoning,
4043
retry,
4144
canCancel,
@@ -48,8 +51,9 @@ export const SendMessageProvider = ({ children }: { children: React.ReactNode })
4851
value={{
4952
sendMessage,
5053
isResponseLoading,
51-
error,
5254
pendingMessage,
55+
error,
56+
errorSteps,
5357
agentReasoning,
5458
retry,
5559
canCancel,

x-pack/platform/plugins/shared/onechat/public/application/context/send_message/use_pending_message_state.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { useState } from 'react';
1010
import { newConversationId } from '../../utils/new_conversation';
1111

1212
interface PendingMessageState {
13-
error?: unknown;
1413
pendingMessage?: string;
1514
}
1615

@@ -44,15 +43,5 @@ export const usePendingMessageState = ({ conversationId }: { conversationId?: st
4443
delete state.pendingMessage;
4544
});
4645
},
47-
setError: (error: unknown) => {
48-
updateState((state) => {
49-
state.error = error;
50-
});
51-
},
52-
removeError: () => {
53-
updateState((state) => {
54-
delete state.error;
55-
});
56-
},
5746
};
5847
};

x-pack/platform/plugins/shared/onechat/public/application/context/send_message/use_send_message_mutation.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
*/
77

88
import { useMutation } from '@kbn/react-query';
9-
import { useRef, useState, useMemo } from 'react';
9+
import { useRef, useState, useMemo, useCallback, useEffect } from 'react';
1010
import { toToolMetadata } from '@kbn/onechat-browser/tools/browser_api_tool';
1111
import { useKibana } from '@kbn/kibana-react-plugin/public';
12-
import { useAgentId } from '../../hooks/use_conversation';
12+
import type { ConversationRoundStep } from '@kbn/onechat-common/chat/conversation';
13+
import { useAgentId, useConversation } from '../../hooks/use_conversation';
1314
import { useConversationContext } from '../conversation/conversation_context';
1415
import { useConversationId } from '../conversation/use_conversation_id';
1516
import { useOnechatServices } from '../../hooks/use_onechat_service';
@@ -32,10 +33,26 @@ export const useSendMessageMutation = ({ connectorId }: UseSendMessageMutationPr
3233
const [isResponseLoading, setIsResponseLoading] = useState(false);
3334
const [agentReasoning, setAgentReasoning] = useState<string | null>(null);
3435
const conversationId = useConversationId();
36+
const { conversation } = useConversation();
3537
const isMutatingNewConversationRef = useRef(false);
3638
const agentId = useAgentId();
3739
const messageControllerRef = useRef<AbortController | null>(null);
3840

41+
const [error, setError] = useState<unknown | null>(null);
42+
const [errorSteps, setErrorSteps] = useState<ConversationRoundStep[]>([]);
43+
44+
const removeError = useCallback(() => {
45+
setError(null);
46+
setErrorSteps([]);
47+
}, []);
48+
49+
useEffect(() => {
50+
// Clear errors any time conversation id changes - we do not persist it.
51+
if (conversationId) {
52+
removeError();
53+
}
54+
}, [conversationId, removeError]);
55+
3956
const browserApiToolsMetadata = useMemo(() => {
4057
if (!browserApiTools) return undefined;
4158
return browserApiTools.map(toToolMetadata);
@@ -46,11 +63,9 @@ export const useSendMessageMutation = ({ connectorId }: UseSendMessageMutationPr
4663
}, [services.notifications?.toasts]);
4764

4865
const {
49-
pendingMessageState: { error, pendingMessage },
66+
pendingMessageState: { pendingMessage },
5067
setPendingMessage,
5168
removePendingMessage,
52-
setError,
53-
removeError,
5469
} = usePendingMessageState({ conversationId });
5570
const subscribeToChatEvents = useSubscribeToChatEvents({
5671
setAgentReasoning,
@@ -115,6 +130,10 @@ export const useSendMessageMutation = ({ connectorId }: UseSendMessageMutationPr
115130
setIsResponseLoading(false);
116131
reportConverseError(err, { connectorId });
117132
setError(err);
133+
const steps = conversation?.rounds?.at(-1)?.steps;
134+
if (steps) {
135+
setErrorSteps(steps);
136+
}
118137
// When we error, we should immediately remove the round rather than waiting for a refetch after invalidation
119138
// Otherwise, the error round and the optimistic round will be visible together.
120139
conversationActions.removeOptimisticRound();
@@ -134,6 +153,7 @@ export const useSendMessageMutation = ({ connectorId }: UseSendMessageMutationPr
134153
sendMessage: mutate,
135154
isResponseLoading,
136155
error,
156+
errorSteps,
137157
pendingMessage,
138158
agentReasoning,
139159
retry: () => {

x-pack/platform/plugins/shared/onechat/public/application/hooks/use_conversation.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,20 @@ export const useConversationTitle = () => {
9696

9797
export const useConversationRounds = () => {
9898
const { conversation } = useConversation();
99-
const { pendingMessage, error } = useSendMessage();
99+
const { pendingMessage, error, errorSteps } = useSendMessage();
100100

101101
const conversationRounds = useMemo(() => {
102102
const rounds = conversation?.rounds ?? [];
103103
if (Boolean(error) && pendingMessage) {
104-
const pendingRound = createNewRound({ userMessage: pendingMessage, roundId: '' });
104+
const pendingRound = createNewRound({
105+
userMessage: pendingMessage,
106+
roundId: '',
107+
steps: errorSteps,
108+
});
105109
return [...rounds, pendingRound];
106110
}
107111
return rounds;
108-
}, [conversation?.rounds, error, pendingMessage]);
112+
}, [conversation?.rounds, error, errorSteps, pendingMessage]);
109113

110114
return conversationRounds;
111115
};

x-pack/platform/plugins/shared/onechat/public/application/utils/new_conversation.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* 2.0.
66
*/
77

8-
import type { Conversation, ConversationRound } from '@kbn/onechat-common';
8+
import type { Conversation, ConversationRound, ConversationRoundStep } from '@kbn/onechat-common';
99
import type { Attachment } from '@kbn/onechat-common/attachments';
1010
import { oneChatDefaultAgentId } from '@kbn/onechat-common';
1111

@@ -29,16 +29,18 @@ export const createNewRound = ({
2929
userMessage,
3030
attachments,
3131
roundId = pendingRoundId,
32+
steps = [],
3233
}: {
3334
userMessage: string;
3435
attachments?: Attachment[];
3536
roundId?: string;
37+
steps?: ConversationRoundStep[];
3638
}): ConversationRound => {
3739
return {
3840
id: roundId,
3941
input: { message: userMessage, attachments },
4042
response: { message: '' },
41-
steps: [],
43+
steps,
4244
started_at: new Date().toISOString(),
4345
time_to_first_token: 0,
4446
time_to_last_token: 0,

0 commit comments

Comments
 (0)