Skip to content

Commit 45b14b1

Browse files
committed
wip(chatdb): fetch messages for thread.
1 parent 71457eb commit 45b14b1

File tree

11 files changed

+173
-99
lines changed

11 files changed

+173
-99
lines changed

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

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
useCapsForToolUse,
1212
useAgentUsage,
1313
} from "../../hooks";
14-
import { type Config } from "../../features/Config/configSlice";
14+
// import { type Config } from "../../features/Config/configSlice";
1515
import {
1616
enableSend,
1717
selectIsStreaming,
@@ -31,19 +31,15 @@ import { Checkpoints } from "../../features/Checkpoints";
3131
import { SuggestNewChat } from "../ChatForm/SuggestNewChat";
3232

3333
export type ChatProps = {
34-
host: Config["host"];
35-
tabbed: Config["tabbed"];
36-
backFromChat: () => void;
37-
style?: React.CSSProperties;
38-
unCalledTools: boolean;
39-
maybeSendToSidebar: ChatFormProps["onClose"];
34+
// host: Config["host"];
35+
// tabbed: Config["tabbed"];
36+
// backFromChat: () => void;
37+
// style?: React.CSSProperties;
38+
// unCalledTools: boolean;
39+
// maybeSendToSidebar: ChatFormProps["onClose"];
4040
};
4141

42-
export const Chat: React.FC<ChatProps> = ({
43-
style,
44-
unCalledTools,
45-
maybeSendToSidebar,
46-
}) => {
42+
export const Chat: React.FC<ChatProps> = () => {
4743
const dispatch = useAppDispatch();
4844

4945
const [isViewingRawJSON, setIsViewingRawJSON] = useState(false);
@@ -58,6 +54,17 @@ export const Chat: React.FC<ChatProps> = ({
5854

5955
const threadNewChatSuggested = useAppSelector(selectThreadNewChatSuggested);
6056
const messages = useAppSelector(selectMessages);
57+
58+
// can be a selector
59+
const unCalledTools = React.useMemo(() => {
60+
if (messages.length === 0) return false;
61+
const last = messages[messages.length - 1];
62+
if (last.role !== "assistant") return false;
63+
const maybeTools = last.tool_calls;
64+
if (maybeTools && maybeTools.length > 0) return true;
65+
return false;
66+
}, [messages]);
67+
6168
const capsForToolUse = useCapsForToolUse();
6269
const { disableInput } = useAgentUsage();
6370

@@ -103,22 +110,21 @@ export const Chat: React.FC<ChatProps> = ({
103110
return (
104111
<DropzoneProvider asChild>
105112
<Flex
106-
style={style}
107113
direction="column"
108114
flexGrow="1"
109115
width="100%"
110116
overflowY="auto"
111117
justify="between"
112118
px="1"
113119
>
120+
{" "}
121+
{/** change messages? */}
114122
<ChatContent
115123
key={`chat-content-${chatId}`}
116124
onRetry={retryFromIndex}
117125
onStopStreaming={abort}
118126
/>
119-
120127
{shouldCheckpointsPopupBeShown && <Checkpoints />}
121-
122128
<AgentUsage />
123129
<SuggestNewChat
124130
shouldBeVisible={
@@ -138,14 +144,11 @@ export const Chat: React.FC<ChatProps> = ({
138144
</Card>
139145
</Flex>
140146
)}
141-
142147
<ChatForm
143148
key={chatId} // TODO: think of how can we not trigger re-render on chatId change (checkboxes)
144149
onSubmit={handleSummit}
145-
onClose={maybeSendToSidebar}
146150
unCalledTools={unCalledTools}
147151
/>
148-
149152
<Flex justify="between" pl="1" pr="1" pt="1">
150153
{/* Two flexboxes are left for the future UI element on the right side */}
151154
{messages.length > 0 && (

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

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback } from "react";
1+
import React, { memo, useCallback, useEffect, useMemo } from "react";
22
import { Flex, Box } from "@radix-ui/themes";
33
import { ScrollArea } from "../ScrollArea";
44
import { HistoryItem } from "./HistoryItem";
@@ -13,7 +13,6 @@ import {
1313
chatDbActions,
1414
} from "../../features/ChatDB/chatDbSlice";
1515
import { subscribeToThreadsThunk } from "../../services/refact/chatdb";
16-
import { restoreChat } from "../../features/Chat/Thread/actions";
1716
import { push } from "../../features/Pages/pagesSlice";
1817
import { CThread } from "../../services/refact/types";
1918

@@ -25,12 +24,21 @@ import { CThread } from "../../services/refact/types";
2524
// currentChatId?: string;
2625
// };
2726

28-
export const ChatHistory: React.FC = () => {
29-
// const sortedHistory = getHistory({ history });
27+
function useGetHistory() {
28+
// todo: search
3029
const dispatch = useAppDispatch();
31-
void dispatch(subscribeToThreadsThunk());
32-
const history = useAppSelector(chatDbSelectors.getChats);
33-
// TODO: should be a request to the lsp, if supported
30+
const history = useAppSelector(chatDbSelectors.getChats, {
31+
devModeChecks: { stabilityCheck: "never" },
32+
});
33+
const isLoading = useAppSelector(chatDbSelectors.getLoading);
34+
35+
useEffect(() => {
36+
const thunk = dispatch(subscribeToThreadsThunk());
37+
return () => {
38+
thunk.abort("unmounted");
39+
};
40+
}, [dispatch]);
41+
3442
const onDeleteHistoryItem = useCallback(
3543
(id: string) => {
3644
dispatch(chatDbActions.deleteCThread(id));
@@ -40,12 +48,22 @@ export const ChatHistory: React.FC = () => {
4048

4149
const onHistoryItemClick = useCallback(
4250
(thread: CThread) => {
43-
dispatch(restoreChat(thread));
44-
dispatch(push({ name: "chat" }));
51+
dispatch(push({ name: "chat", threadId: thread.cthread_id }));
4552
},
4653
[dispatch],
4754
);
4855

56+
return {
57+
history,
58+
isLoading,
59+
onHistoryItemClick,
60+
onDeleteHistoryItem,
61+
};
62+
}
63+
64+
export const ChatHistory: React.FC = () => {
65+
const { history, onHistoryItemClick, onDeleteHistoryItem } = useGetHistory();
66+
4967
return (
5068
<Box
5169
style={{

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import React, { useCallback } from "react";
1+
import React from "react";
22
import { Box, Flex } from "@radix-ui/themes";
33
import { ChatHistory, type ChatHistoryProps } from "../ChatHistory";
44
import { Spinner } from "@radix-ui/themes";
5-
import { useAppSelector, useAppDispatch } from "../../hooks";
6-
import { deleteChatById } from "../../features/History/historySlice";
7-
import { push } from "../../features/Pages/pagesSlice";
8-
import { restoreChat, type ChatThread } from "../../features/Chat/Thread";
5+
96
import { FeatureMenu } from "../../features/Config/FeatureMenu";
10-
import { subscribeToThreadsThunk } from "../../services/refact/chatdb";
117

128
export type SidebarProps = {
139
takingNotes: boolean;

refact-agent/gui/src/features/App.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,7 @@ export const InnerApp: React.FC<AppProps> = ({ style }: AppProps) => {
175175
}}
176176
/>
177177
)}
178-
{page.name === "chat" && (
179-
<Chat
180-
host={config.host}
181-
tabbed={config.tabbed}
182-
backFromChat={goBack}
183-
/>
184-
)}
178+
{page.name === "chat" && <Chat threadId={page.threadId} />}
185179
{page.name === "fill in the middle debug page" && (
186180
<FIMDebug host={config.host} tabbed={config.tabbed} />
187181
)}
Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,26 @@
1-
import React from "react";
2-
import type { Config } from "../Config/configSlice";
1+
import React, { useEffect } from "react";
2+
import { v4 as uuid } from "uuid";
33
import { Chat as ChatComponent } from "../../components/Chat";
4-
import { useAppSelector } from "../../hooks";
5-
import { selectMessages } from "./Thread";
4+
import { subscribeToThreadMessagesThunk } from "../../services/refact/chatdb";
5+
import { useAppDispatch } from "../../hooks";
66

77
export type ChatProps = {
8-
host: Config["host"];
9-
tabbed: Config["tabbed"];
10-
style?: React.CSSProperties;
11-
backFromChat: () => void;
8+
threadId?: string;
129
};
1310

14-
export const Chat: React.FC<ChatProps> = ({
15-
style,
16-
backFromChat,
17-
host,
18-
tabbed,
19-
}) => {
20-
const messages = useAppSelector(selectMessages);
11+
function useMessagesForThread(threadId: string) {
12+
const dispatch = useAppDispatch();
13+
useEffect(() => {
14+
const thunk = dispatch(subscribeToThreadMessagesThunk(threadId));
15+
return () => {
16+
thunk.abort(threadId);
17+
};
18+
}, [dispatch, threadId]);
19+
}
2120

22-
const sendToSideBar = () => {
23-
// TODO:
24-
};
25-
26-
const maybeSendToSideBar =
27-
host === "vscode" && tabbed ? sendToSideBar : undefined;
28-
29-
// can be a selector
30-
const unCalledTools = React.useMemo(() => {
31-
if (messages.length === 0) return false;
32-
const last = messages[messages.length - 1];
33-
if (last.role !== "assistant") return false;
34-
const maybeTools = last.tool_calls;
35-
if (maybeTools && maybeTools.length > 0) return true;
36-
return false;
37-
}, [messages]);
38-
39-
return (
40-
<ChatComponent
41-
style={style}
42-
host={host}
43-
tabbed={tabbed}
44-
backFromChat={backFromChat}
45-
unCalledTools={unCalledTools}
46-
maybeSendToSidebar={maybeSendToSideBar}
47-
/>
48-
);
21+
export const Chat: React.FC<ChatProps> = (props) => {
22+
// TBD: does sqlite have a uuid function?
23+
const threadId = props.threadId ?? uuid();
24+
useMessagesForThread(threadId);
25+
return <ChatComponent key={threadId} />;
4926
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
2+
import { CMessage } from "../../services/refact";
3+
4+
type InitialState = {
5+
threadId: string;
6+
messages: CMessage[];
7+
loading: boolean;
8+
error: null | string;
9+
};
10+
11+
const initialState: InitialState = {
12+
threadId: "",
13+
messages: [],
14+
loading: false,
15+
error: null,
16+
};
17+
18+
export const chatDbMessageSlice = createSlice({
19+
name: "chatDbMessages",
20+
initialState,
21+
reducers: {
22+
setThreadId: (state, action: PayloadAction<string>) => {
23+
state.threadId = action.payload;
24+
},
25+
},
26+
});

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const initialState: ChatDbState = {
1313
chats: {},
1414
};
1515

16-
export const chatDbSlice = createSlice({
17-
name: "chatDb",
16+
export const chatDbThreadsSlice = createSlice({
17+
name: "chatDbThreads",
1818
initialState,
1919
reducers: {
2020
reset: () => initialState,
@@ -46,5 +46,5 @@ export const chatDbSlice = createSlice({
4646
},
4747
});
4848

49-
export const chatDbActions = chatDbSlice.actions;
50-
export const chatDbSelectors = chatDbSlice.selectors;
49+
export const chatDbActions = chatDbThreadsSlice.actions;
50+
export const chatDbSelectors = chatDbThreadsSlice.selectors;

refact-agent/gui/src/features/Pages/pagesSlice.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface HistoryList {
1414

1515
export interface ChatPage {
1616
name: "chat";
17+
threadId?: string;
1718
}
1819

1920
export interface FIMDebugPage {

0 commit comments

Comments
 (0)