Skip to content

Commit

Permalink
Moved stream status into the last message object
Browse files Browse the repository at this point in the history
  • Loading branch information
Dayana Ilieva committed May 9, 2024
1 parent 5d1d89e commit 027af43
Show file tree
Hide file tree
Showing 14 changed files with 2,052 additions and 2,051 deletions.
2 changes: 0 additions & 2 deletions __tests__/feature/chat-history.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ describe('Chat-history event works and visualizes items accordingly', () => {

const { chat } = root.store.getState();
expect(chat.isLoading).toBe(false);
expect(chat.isStreaming).toBe(false);
});

test('email form submitted does not submit the email when the field is empty', async () => {
Expand Down Expand Up @@ -293,7 +292,6 @@ describe('Chat-history event works and visualizes items accordingly', () => {

const { chat } = root.store.getState();
expect(chat.isLoading).toBe(false);
expect(chat.isStreaming).toBe(false);
});

test('on chat-history event with errors in the callback visualizes the error', async () => {
Expand Down
3,947 changes: 1,970 additions & 1,977 deletions dist/index.es.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.es.js.map

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions dist/index.umd.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.umd.js.map

Large diffs are not rendered by default.

16 changes: 6 additions & 10 deletions src/components/Stream/assistant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Markdown from 'react-markdown';
import { Definition } from '../../config/enums';
import { useAppSelector } from '../../hooks';
import { AssistantProps } from '../../interfaces/component';
import { getChat, getLastHistoryId, sortBySequence } from '../../store/slices/chat';
import { getLastHistoryId, sortBySequence } from '../../store/slices/chat';
import { getMeta } from '../../store/slices/meta';
import { extractVideoCode, uuidV4 } from '../../utils';
import { replaceNewRowSymbols } from '../../utils/formatting';
Expand All @@ -14,27 +14,24 @@ import OptionList from './options';
import { flickerEffect } from './variants';

const Assistant = ({ message, itemId }: AssistantProps) => {
const { isStreaming } = useAppSelector(getChat);
const { pd } = useAppSelector(getMeta);
const isLast = useAppSelector(getLastHistoryId) === itemId;
const { base: baseFlicker } = flickerEffect({ isTyping: isStreaming && isLast });
const { base: baseFlicker } = flickerEffect({ isTyping: !!message.isStreaming });
const sortedContent = [...message.content].sort(sortBySequence);

return (
<>
{sortedContent.map((it) => {
if (it.type === Definition.text) {
return (
<div
key={uuidV4()}
className="tw--flex tw--flex-col tw--space-y-[10px]"
data-e2e="assistant-text"
>
<div key={uuidV4()} className="tw--flex tw--flex-col tw--space-y-[10px]" data-e2e="assistant-text">
<span className={baseFlicker()}>
<Markdown
key={uuidV4()}
components={{
a(props) { return <MarkdownLink properties={props} />; },
a(props) {
return <MarkdownLink properties={props} />;
},
}}
>
{replaceNewRowSymbols(it[it.type] || '')}
Expand Down Expand Up @@ -85,7 +82,6 @@ const Assistant = ({ message, itemId }: AssistantProps) => {
if (it.type === Definition.email) {
return it[it.type];
}

})}
</>
);
Expand Down
51 changes: 25 additions & 26 deletions src/components/Stream/bubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,31 @@ import { streamBubble as variant } from './variants';
const StreamBubble = ({ itemId }: { itemId: string }) => {
const record = useAppSelector(getRecordById(itemId));

return (record && (
<div className={variant({ type: record.role }).base()}
data-e2e={record.role === Roles.assistant ? 'stream-assistant-msg' : 'user-msg'}
>
{record.role === Roles.assistant
? (
<MemoizedAssistant
message={record}
itemId={itemId}
/>
)
:
[...record.content].map((record) =>
<User
key={uuidV4()}
record={{
text: record.text || '',
resend: record.resend || false,
sent: record.sent || true,
groupId: record.groupId || '',
itemId
}}
/>)
}
</div>
));
return (
record && (
<div
className={variant({ type: record.role }).base()}
data-e2e={record.role === Roles.assistant ? 'stream-assistant-msg' : 'user-msg'}
>
{record.role === Roles.assistant ? (
<MemoizedAssistant message={record} itemId={itemId} />
) : (
[...record.content].map((record) => (
<User
key={uuidV4()}
record={{
text: record.text || '',
resend: record.resend || false,
sent: record.sent || true,
groupId: record.groupId || '',
itemId,
}}
/>
))
)}
</div>
)
);
};

export const MemoizedStreamBubble = React.memo(StreamBubble);
Expand Down
8 changes: 6 additions & 2 deletions src/hooks/foot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useAppSelector } from '.';
export const useFootProps = () => {
const { cid, systemType, marketing, pd } = useAppSelector(getMeta);
const { translations, purpose, specialUrls } = useAppSelector(getConfig);
const { isLoading, isStreaming, record, error: streamError, thread } = useAppSelector(getChat);
const { isLoading, record, error: streamError, thread } = useAppSelector(getChat);

// @ts-expect-error passing only the needed prop
const currentThread = getThreadId({ chat: { thread } });
Expand All @@ -30,7 +30,7 @@ export const useFootProps = () => {
currentEmail,
translations,
pd,
isStreaming,
isStreaming: false,
isPaymentButtonVisible: false,
isPaymentFormVisible: false,
isEmailFormVisible: false,
Expand All @@ -51,6 +51,10 @@ export const useFootProps = () => {
const hasPaymentIntent = lastMsg && lastMsg?.content.find((m) => m.payment);
const hasEmailIntent = lastMsg && lastMsg?.content.find((m) => m.email);

if (lastMsg && 'isStreaming' in lastMsg) {
staticProps.isStreaming = !!lastMsg.isStreaming;
}

if (isLastAssistantMsg && hasPaymentIntent) {
return {
...staticProps,
Expand Down
5 changes: 3 additions & 2 deletions src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,11 @@ export interface UserHistoryDataFiller {

export interface AssistantHistoryDataFiller {
id: string;
content?: AssistantRecord;
sequence?: number;
isStreaming: boolean;
term: string;
threadId: string;
sequence?: number;
content?: AssistantRecord;
}

export interface AssistantHistoryInitialMessage {
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface ChatRecord {
id: string;
role: string;
time?: number;
isStreaming?: boolean;
content: Array<MessageProperties>;
}

Expand All @@ -24,7 +25,6 @@ export interface ChatState {
lastGroupId: string;
connected: boolean;
closed: boolean;
isStreaming: boolean;
record: {
[key: string]: {
historyData: Record<string, ChatRecord>;
Expand Down
18 changes: 13 additions & 5 deletions src/middleware/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
setConnected,
setError,
setIsLoading,
setIsStreaming,
setLastGroupPointer,
setOutgoing,
setTypingTimeoutExpired,
Expand Down Expand Up @@ -59,7 +58,9 @@ const chatMiddleware: Middleware = (store) => (next) => (action) => {
};

const handleMessageSending = (data: ClientMessage): void => {
if (action.$isSync) { return; }
if (action.$isSync) {
return;
}

if (data.role === Roles.user) {
store.dispatch(setIsLoading());
Expand Down Expand Up @@ -189,7 +190,6 @@ const chatMiddleware: Middleware = (store) => (next) => (action) => {
Events.chatHistory,
({ history: servedHistory, errors, region, term: servedTerm, threadId }: ServerData) => {
store.dispatch(resetIsLoading());
store.dispatch(setIsStreaming(false));
store.dispatch(setRegion(region));
store.dispatch(initiateThread({ threadId, term: servedTerm }));

Expand Down Expand Up @@ -233,7 +233,6 @@ const chatMiddleware: Middleware = (store) => (next) => (action) => {
);

socket.on(Events.streamStart, ({ id, term, threadId }: { id: string; term: string; threadId: string }) => {
store.dispatch(setIsStreaming(true));
store.dispatch(resetIsLoading());
store.dispatch(resetOutgoing());
store.dispatch(resetError());
Expand All @@ -242,6 +241,7 @@ const chatMiddleware: Middleware = (store) => (next) => (action) => {
id,
term,
threadId,
isStreaming: true,
}),
);
});
Expand All @@ -262,6 +262,7 @@ const chatMiddleware: Middleware = (store) => (next) => (action) => {
sequence: data.sequence,
term: data.term,
threadId: data.threadId,
isStreaming: true,
content: {
type: data.type,
[data.type]: data[data.type],
Expand All @@ -277,7 +278,14 @@ const chatMiddleware: Middleware = (store) => (next) => (action) => {
);

socket.on(Events.streamEnd, ({ id, term, threadId }: { id: string; term: string; threadId: string }) => {
store.dispatch(setIsStreaming(false));
store.dispatch(
fillAssistantHistoryData({
id,
term,
threadId,
isStreaming: false,
}),
);
});

socket.on(Events.streamError, onError);
Expand Down
1 change: 0 additions & 1 deletion src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export const store = configureStore({
intentionsMiddleware,
createStateSyncMiddleware({
whitelist: [
'chat/setIsStreaming',
'chat/resetIsLoading',
'chat/resetOutgoing',
'chat/resetError',
Expand Down
1 change: 0 additions & 1 deletion src/store/initialState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export const chat: ChatState = {
lastGroupId: uuidV4(),
connected: false,
closed: false,
isStreaming: false,
record: {},
thread: {},
};
Expand Down
22 changes: 13 additions & 9 deletions src/store/slices/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,12 @@ const configSlice = createSlice({
for (let i = 0; i < serverIds.length; i++) {
const currentId = serverIds[i];

if (!clientIds.includes(currentId)) {
if (clientIds.includes(currentId)) {
draft.record[threadId].historyData[currentId] = {
...draft.record[threadId].historyData[currentId],
isStreaming: false,
};
} else {
clientIds.splice(i, 0, currentId);

draft.record[threadId].historyData[currentId] = history[i];
Expand Down Expand Up @@ -103,20 +108,23 @@ const configSlice = createSlice({
},
fillAssistantHistoryData(
state,
{ payload: { id, content, sequence, threadId } }: PayloadAction<AssistantHistoryDataFiller>,
{ payload: { id, content, sequence, threadId, isStreaming } }: PayloadAction<AssistantHistoryDataFiller>,
) {
return produce(state, (draft: Draft<ChatState>) => {
if (draft.record[threadId] && !draft.record[threadId].historyData[id]) {
draft.record[threadId].historyData[id] = { id, role: Roles.assistant, content: [] };
draft.record[threadId].historyData[id] = { id, role: Roles.assistant, isStreaming, content: [] };
draft.record[threadId].historyIds.push(id);
return;
}

if (draft.record[threadId]?.historyData[id]) {
draft.record[threadId].historyData[id].isStreaming = isStreaming;
}

if (!content) {
return;
}


if (!draft.record[threadId]) {
return;
}
Expand All @@ -129,7 +137,7 @@ const configSlice = createSlice({
) {
draft.record[threadId].historyData[id].content = getUnifiedSequence(
draft.record[threadId].historyData[id].content as Array<AssistantRecord>,
content
content,
);
return;
}
Expand Down Expand Up @@ -232,9 +240,6 @@ const configSlice = createSlice({
resetError(state) {
state.error = initialState.error;
},
setIsStreaming(state, { payload }: PayloadAction<boolean>) {
state.isStreaming = payload;
},
resetHistory(state, { payload: { thread } }) {
state.record[thread] = { historyData: {}, historyIds: [] };
},
Expand Down Expand Up @@ -291,7 +296,6 @@ export const {
setClosed,
showResendIcon,
resendMessage,
setIsStreaming,
fillAssistantHistoryData,
fillUserHistoryData,
resetHistory,
Expand Down

0 comments on commit 027af43

Please sign in to comment.