Skip to content

Commit 6600ed5

Browse files
committed
wip(chat-db): render message tree.
1 parent 96be369 commit 6600ed5

File tree

7 files changed

+53
-36
lines changed

7 files changed

+53
-36
lines changed

refact-agent/gui/src/components/Chat/Chat.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useCallback, useEffect, useState } from "react";
2-
import { ChatForm, ChatFormProps } from "../ChatForm";
2+
import { ChatForm } from "../ChatForm";
33
import { ChatContent } from "../ChatContent";
44
import { Flex, Button, Text, Card } from "@radix-ui/themes";
55
import {

refact-agent/gui/src/components/ChatContent/ChatContent.tsx

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222
selectIntegration,
2323
selectIsStreaming,
2424
selectIsWaiting,
25-
selectMessages,
2625
selectThread,
2726
selectThreadUsage,
2827
} from "../../features/Chat/Thread/selectors";
@@ -35,6 +34,8 @@ import { telemetryApi } from "../../services/refact/telemetry";
3534
import { PlaceHolderText } from "./PlaceHolderText";
3635
import { UsageCounter } from "../UsageCounter";
3736
import { getConfirmationPauseStatus } from "../../features/ToolConfirmation/confirmationSlice";
37+
import { MessageNode } from "../MessageNode";
38+
import { chatDbMessagesSliceSelectors } from "../../features/ChatDB/chatDbMessagesSlice";
3839

3940
export type ChatContentProps = {
4041
onRetry: (index: number, question: UserMessage["content"]) => void;
@@ -43,11 +44,9 @@ export type ChatContentProps = {
4344

4445
export const ChatContent: React.FC<ChatContentProps> = ({
4546
onStopStreaming,
46-
onRetry,
4747
}) => {
4848
const dispatch = useAppDispatch();
4949
const scrollRef = useRef<HTMLDivElement>(null);
50-
const messages = useAppSelector(selectMessages);
5150
const isStreaming = useAppSelector(selectIsStreaming);
5251
const thread = useAppSelector(selectThread);
5352
const threadUsage = useAppSelector(selectThreadUsage);
@@ -57,6 +56,9 @@ export const ChatContent: React.FC<ChatContentProps> = ({
5756
telemetryApi.useLazySendTelemetryChatEventQuery();
5857
const integrationMeta = useAppSelector(selectIntegration);
5958
const isWaitingForConfirmation = useAppSelector(getConfirmationPauseStatus);
59+
const messageTree = useAppSelector(
60+
chatDbMessagesSliceSelectors.selectMessageTree,
61+
);
6062

6163
const {
6264
handleScroll,
@@ -67,10 +69,6 @@ export const ChatContent: React.FC<ChatContentProps> = ({
6769
scrollRef,
6870
});
6971

70-
const onRetryWrapper = (index: number, question: UserMessage["content"]) => {
71-
onRetry(index, question);
72-
};
73-
7472
const handleReturnToConfigurationClick = useCallback(() => {
7573
// console.log(`[DEBUG]: going back to configuration page`);
7674
// TBD: should it be allowed to run in the background?
@@ -121,10 +119,11 @@ export const ChatContent: React.FC<ChatContentProps> = ({
121119
p="2"
122120
gap="1"
123121
>
124-
{messages.length === 0 && <PlaceHolderText />}
125-
{renderMessages(messages, onRetryWrapper)}
126-
<UncommittedChangesWarning />
127-
{threadUsage && messages.length > 0 && <UsageCounter />}
122+
{!messageTree && <PlaceHolderText />}
123+
{/* {renderMessages(messages, onRetryWrapper)} */}
124+
<MessageNode>{messageTree}</MessageNode>
125+
{!messageTree && <UncommittedChangesWarning />}
126+
{threadUsage && messageTree && <UsageCounter />}
128127

129128
<Container py="4">
130129
<Spinner
@@ -176,7 +175,8 @@ export const ChatContent: React.FC<ChatContentProps> = ({
176175

177176
ChatContent.displayName = "ChatContent";
178177

179-
function renderMessages(
178+
// TODO: can delete
179+
function _renderMessages(
180180
messages: ChatMessages,
181181
onRetry: (index: number, question: UserMessage["content"]) => void,
182182
memo: React.ReactNode[] = [],
@@ -185,13 +185,13 @@ function renderMessages(
185185
if (messages.length === 0) return memo;
186186
const [head, ...tail] = messages;
187187
if (head.role === "tool") {
188-
return renderMessages(tail, onRetry, memo, index + 1);
188+
return _renderMessages(tail, onRetry, memo, index + 1);
189189
}
190190

191191
if (head.role === "plain_text") {
192192
const key = "plain-text-" + index;
193193
const nextMemo = [...memo, <PlainText key={key}>{head.content}</PlainText>];
194-
return renderMessages(tail, onRetry, nextMemo, index + 1);
194+
return _renderMessages(tail, onRetry, nextMemo, index + 1);
195195
}
196196

197197
if (head.role === "assistant") {
@@ -207,7 +207,7 @@ function renderMessages(
207207
/>,
208208
];
209209

210-
return renderMessages(tail, onRetry, nextMemo, index + 1);
210+
return _renderMessages(tail, onRetry, nextMemo, index + 1);
211211
}
212212

213213
if (head.role === "user") {
@@ -219,13 +219,13 @@ function renderMessages(
219219
{head.content}
220220
</UserInput>,
221221
];
222-
return renderMessages(tail, onRetry, nextMemo, index + 1);
222+
return _renderMessages(tail, onRetry, nextMemo, index + 1);
223223
}
224224

225225
if (isChatContextFileMessage(head)) {
226226
const key = "context-file-" + index;
227227
const nextMemo = [...memo, <ContextFiles key={key} files={head.content} />];
228-
return renderMessages(tail, onRetry, nextMemo, index + 1);
228+
return _renderMessages(tail, onRetry, nextMemo, index + 1);
229229
}
230230

231231
if (isDiffMessage(head)) {
@@ -240,13 +240,13 @@ function renderMessages(
240240

241241
const nextMemo = [...memo, <GroupedDiffs key={key} diffs={diffMessages} />];
242242

243-
return renderMessages(
243+
return _renderMessages(
244244
nextTail,
245245
onRetry,
246246
nextMemo,
247247
index + diffMessages.length,
248248
);
249249
}
250250

251-
return renderMessages(tail, onRetry, memo, index + 1);
251+
return _renderMessages(tail, onRetry, memo, index + 1);
252252
}

refact-agent/gui/src/components/ChatLinks/UncommittedChangesWarning.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { Flex, Separator } from "@radix-ui/themes";
55
import {
66
selectIsStreaming,
77
selectIsWaiting,
8-
selectMessages,
98
selectThreadToolUse,
109
} from "../../features/Chat";
1110
import { getErrorMessage } from "../../features/Errors/errorsSlice";
@@ -18,15 +17,13 @@ export const UncommittedChangesWarning: React.FC = () => {
1817
const error = useAppSelector(getErrorMessage);
1918
const information = useAppSelector(getInformationMessage);
2019
const toolUse = useAppSelector(selectThreadToolUse);
21-
const messages = useAppSelector(selectMessages);
2220

2321
const hasCallout = React.useMemo(() => {
2422
return !!error || !!information;
2523
}, [error, information]);
2624

2725
if (
2826
toolUse !== "agent" ||
29-
messages.length !== 0 ||
3027
hasCallout ||
3128
isStreaming ||
3229
isWaiting ||

refact-agent/gui/src/components/MessageNode/MessageNode.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ const ElementForNodeMessage: React.FC<{ message: ChatMessage }> = ({
5757
return false;
5858
};
5959

60-
export type MessageNodeProps = { children?: CMessageNode };
60+
export type MessageNodeProps = { children?: CMessageNode | null };
61+
62+
// TODO: update tracking the end point
6163
export const MessageNode: React.FC<MessageNodeProps> = ({ children }) => {
6264
const dispatch = useAppDispatch();
6365

@@ -104,9 +106,25 @@ const UserMessageNode: React.FC<{ children: UserCMessageNode[] }> = ({
104106
children,
105107
}) => {
106108
// info about the node may need to be shared with the user input
109+
const dispatch = useAppDispatch();
107110
const [selectedNodeIndex, setSelectedNodeIndex] = React.useState<number>(0);
108111

109112
const selectedNode = children[selectedNodeIndex];
113+
114+
useEffect(() => {
115+
if (selectedNode.children.length === 0) {
116+
const action = chatDbMessageSliceActions.setEnd({
117+
number: selectedNode.message.cmessage_num,
118+
alt: selectedNode.message.cmessage_alt,
119+
});
120+
dispatch(action);
121+
}
122+
}, [
123+
selectedNode.children.length,
124+
selectedNode.message.cmessage_num,
125+
selectedNode.message.cmessage_alt,
126+
dispatch,
127+
]);
110128
return (
111129
<>
112130
<IconButton

refact-agent/gui/src/features/ChatDB/chatDbMessagesSlice.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
isUserCMessage,
99
} from "../../services/refact";
1010
import { parseOrElse } from "../../utils";
11-
import { makeMessageTree } from "./makeMessageTree";
11+
import { makeMessageTree, sortMessageList } from "./makeMessageTree";
1212
import { pagesSlice } from "../Pages/pagesSlice";
1313

1414
export interface CMessageNode {
@@ -91,12 +91,7 @@ export const chatDbMessageSlice = createSlice({
9191
state.messageList[updateIndex] = message;
9292
} else {
9393
state.messageList.push(message);
94-
state.messageList.sort((a, b) => {
95-
if (a.cmessage_num === b.cmessage_num) {
96-
return a.cmessage_alt - b.cmessage_alt;
97-
}
98-
return a.cmessage_num - b.cmessage_num;
99-
});
94+
state.messageList = sortMessageList(state.messageList);
10095
}
10196
},
10297
setEnd: (state, action: PayloadAction<{ number: number; alt: number }>) => {

refact-agent/gui/src/features/ChatDB/makeMessageTree.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,17 @@ const isRoot = (message: CMessage): boolean => {
66
return message.cmessage_prev_alt === -1;
77
};
88

9+
export function sortMessageList(messages: CMessage[]): CMessage[] {
10+
return messages.slice(0).sort((a, b) => {
11+
if (a.cmessage_num === b.cmessage_num) {
12+
return a.cmessage_alt - b.cmessage_alt;
13+
}
14+
return a.cmessage_num - b.cmessage_num;
15+
});
16+
}
17+
918
export const makeMessageTree = (messages: CMessage[]): CMessageNode | null => {
10-
const sortedMessages = messages
11-
.slice()
12-
.sort((a, b) => a.cmessage_num - b.cmessage_num);
19+
const sortedMessages = sortMessageList(messages);
1320

1421
const [nodes, roots] = partition(sortedMessages, isRoot);
1522
if (roots.length === 0) return null;

refact-agent/gui/src/hooks/useThreadMessageSubmit.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ export function useThreadMessageSubmit() {
7575
const systemCMessage: CMessage = {
7676
cmessage_belongs_to_cthread_id: threadId,
7777
cmessage_alt: 0,
78-
cmessage_num: -1,
79-
cmessage_prev_alt: 0,
78+
cmessage_num: 0,
79+
cmessage_prev_alt: -1,
8080
cmessage_usage_model: threadModel, // could be default
8181
cmessage_usage_prompt: 0,
8282
cmessage_usage_completion: 0,

0 commit comments

Comments
 (0)