Skip to content

Commit 52567c0

Browse files
committed
cr
1 parent 7b8aecd commit 52567c0

File tree

5 files changed

+181
-95
lines changed

5 files changed

+181
-95
lines changed

frontend/app/components/GeneratingQuestionsToolUI.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export const useGeneratingQuestionsUI = () =>
6868
<div className="flex flex-col mb-4">
6969
<span className="flex flex-row gap-2 items-center justify-start pb-4 text-gray-300">
7070
<Globe className="w-5 h-5" />
71-
<p className="text-xl">Generated Questions & Sources</p>
71+
<p className="text-xl">Research Plan & Sources</p>
7272
</span>
7373
<div className="mb-10">
7474
<div className="flex flex-wrap items-center justify-start gap-2">

frontend/app/components/ThreadHistory.tsx

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { isToday, isYesterday, isWithinInterval, subDays } from "date-fns";
2-
import { dummyThreads } from "../utils/dummy";
32
import { TooltipIconButton } from "./ui/assistant-ui/tooltip-icon-button";
43
import { Button } from "./ui/button";
5-
import { SquarePen, History } from "lucide-react";
4+
import { SquarePen, History, Trash2 } from "lucide-react";
65
import { Sheet, SheetContent, SheetTrigger } from "./ui/sheet";
76
import { ThreadActual } from "../hooks/useThreads";
87
import { useToast } from "../hooks/use-toast";
98
import { Skeleton } from "./ui/skeleton";
9+
import { useEffect, useState } from "react";
1010

1111
interface ThreadHistoryProps {
1212
isUserThreadsLoading: boolean;
@@ -15,46 +15,76 @@ interface ThreadHistoryProps {
1515
userThreads: ThreadActual[];
1616
userId: string | undefined;
1717
createThread: (id: string) => Promise<any>;
18+
clearMessages: () => void;
1819
assistantId: string | undefined;
1920
switchSelectedThread: (thread: ThreadActual) => void;
2021
getUserThreads: (id: string) => Promise<void>;
22+
deleteThread: (id: string) => Promise<void>;
2123
}
2224

2325
interface ThreadProps {
2426
id: string;
2527
onClick: () => void;
28+
onDelete: () => void;
2629
label: string;
2730
createdAt: Date;
2831
}
2932

30-
const Thread = (props: ThreadProps) => (
31-
<Button
32-
className="px-2 hover:bg-[#393939] hover:text-white justify-start"
33-
size="sm"
34-
variant="ghost"
35-
onClick={props.onClick}
36-
>
37-
<p className="truncate ... text-sm font-light">{props.label}</p>
38-
</Button>
39-
);
33+
const Thread = (props: ThreadProps) => {
34+
const [isHovering, setIsHovering] = useState(false);
35+
36+
return (
37+
<div
38+
className="flex flex-row gap-0 items-center justify-start w-full"
39+
onMouseEnter={() => setIsHovering(true)}
40+
onMouseLeave={() => setIsHovering(false)}
41+
>
42+
<Button
43+
className="px-2 hover:bg-[#393939] hover:text-white justify-start items-center flex-grow min-w-[191px] pr-0"
44+
size="sm"
45+
variant="ghost"
46+
onClick={props.onClick}
47+
>
48+
<p className="truncate text-sm font-light w-full text-left">
49+
{props.label}
50+
</p>
51+
</Button>
52+
{isHovering && (
53+
<TooltipIconButton
54+
tooltip="Delete thread"
55+
variant="ghost"
56+
className="hover:bg-[#373737] flex-shrink-0 p-2"
57+
onClick={props.onDelete}
58+
>
59+
<Trash2 className="w-4 h-4 text-[#575757] hover:text-red-500 transition-colors ease-in" />
60+
</TooltipIconButton>
61+
)}
62+
</div>
63+
);
64+
};
4065

4166
const LoadingThread = () => <Skeleton className="w-full h-8 bg-[#373737]" />;
4267

4368
const convertThreadActualToThreadProps = (
4469
thread: ThreadActual,
4570
switchSelectedThread: (thread: ThreadActual) => void,
71+
deleteThread: (id: string) => void,
4672
): ThreadProps => ({
4773
id: thread.thread_id,
4874
label: thread.values?.messages?.[0].content || "Untitled",
4975
createdAt: new Date(thread.created_at),
5076
onClick: () => {
5177
return switchSelectedThread(thread);
5278
},
79+
onDelete: () => {
80+
return deleteThread(thread.thread_id);
81+
},
5382
});
5483

5584
const groupThreads = (
5685
threads: ThreadActual[],
5786
switchSelectedThread: (thread: ThreadActual) => void,
87+
deleteThread: (id: string) => void,
5888
) => {
5989
const today = new Date();
6090
const yesterday = subDays(today, 1);
@@ -67,14 +97,18 @@ const groupThreads = (
6797
(a, b) =>
6898
new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
6999
)
70-
.map((t) => convertThreadActualToThreadProps(t, switchSelectedThread)),
100+
.map((t) =>
101+
convertThreadActualToThreadProps(t, switchSelectedThread, deleteThread),
102+
),
71103
yesterday: threads
72104
.filter((thread) => isYesterday(new Date(thread.created_at)))
73105
.sort(
74106
(a, b) =>
75107
new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
76108
)
77-
.map((t) => convertThreadActualToThreadProps(t, switchSelectedThread)),
109+
.map((t) =>
110+
convertThreadActualToThreadProps(t, switchSelectedThread, deleteThread),
111+
),
78112
lastSevenDays: threads
79113
.filter((thread) =>
80114
isWithinInterval(new Date(thread.created_at), {
@@ -86,14 +120,18 @@ const groupThreads = (
86120
(a, b) =>
87121
new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
88122
)
89-
.map((t) => convertThreadActualToThreadProps(t, switchSelectedThread)),
123+
.map((t) =>
124+
convertThreadActualToThreadProps(t, switchSelectedThread, deleteThread),
125+
),
90126
older: threads
91127
.filter((thread) => new Date(thread.created_at) < sevenDaysAgo)
92128
.sort(
93129
(a, b) =>
94130
new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
95131
)
96-
.map((t) => convertThreadActualToThreadProps(t, switchSelectedThread)),
132+
.map((t) =>
133+
convertThreadActualToThreadProps(t, switchSelectedThread, deleteThread),
134+
),
97135
};
98136
};
99137

@@ -147,6 +185,7 @@ export function ThreadHistory(props: ThreadHistoryProps) {
147185
const groupedThreads = groupThreads(
148186
props.userThreads,
149187
props.switchSelectedThread,
188+
props.deleteThread,
150189
);
151190

152191
const createThread = async () => {
@@ -163,6 +202,8 @@ export function ThreadHistory(props: ThreadHistoryProps) {
163202
if (currentThread && !currentThread.values && props.isEmpty) {
164203
return;
165204
}
205+
206+
props.clearMessages();
166207
await props.createThread(props.userId);
167208
// Re-fetch threads so that the new thread shows up.
168209
await props.getUserThreads(props.userId);

frontend/app/hooks/useGraph.tsx

Lines changed: 26 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -53,70 +53,25 @@ export interface GraphInput {
5353
messages?: Record<string, any>[];
5454
}
5555

56-
export function useGraph(userId: string | undefined) {
56+
interface UseGraphInput {
57+
userId: string | undefined;
58+
threadId: string | undefined;
59+
}
60+
61+
export function useGraph(inputArgs: UseGraphInput) {
5762
const { toast } = useToast();
58-
const { getThreadById } = useThreads(userId);
63+
const { getThreadById, setThreadId } = useThreads(inputArgs.userId);
5964
const { shareRun } = useRuns();
6065
const [messages, setMessages] = useState<BaseMessage[]>([]);
6166
const [assistantId, setAssistantId] = useState<string>();
62-
const [threadId, setThreadId] = useState<string>();
6367
const [selectedModel, setSelectedModel] =
6468
useState<ModelOptions>("openai/gpt-4o-mini");
6569

66-
useEffect(() => {
67-
if (threadId || typeof window === "undefined" || !userId) return;
68-
searchOrCreateThread(userId);
69-
}, [userId]);
70-
7170
useEffect(() => {
7271
if (assistantId || typeof window === "undefined") return;
7372
getOrCreateAssistant();
7473
}, []);
7574

76-
const searchOrCreateThread = async (id: string) => {
77-
const threadIdCookie = getCookie("clc_py_thread_id");
78-
if (!threadIdCookie) {
79-
await createThread(id);
80-
return;
81-
}
82-
// Thread ID is in cookies.
83-
84-
const thread = await getThreadById(threadIdCookie);
85-
if (!thread.values) {
86-
// No values = no activity. Can keep.
87-
setThreadId(threadIdCookie);
88-
return;
89-
} else {
90-
// Current thread has activity. Create a new thread.
91-
await createThread(id);
92-
return;
93-
}
94-
};
95-
96-
const createThread = async (id: string) => {
97-
setMessages([]);
98-
const client = createClient();
99-
let thread;
100-
try {
101-
thread = await client.threads.create({
102-
metadata: {
103-
user_id: id,
104-
},
105-
});
106-
if (!thread || !thread.thread_id) {
107-
throw new Error("Thread creation failed.");
108-
}
109-
setThreadId(thread.thread_id);
110-
setCookie("clc_py_thread_id", thread.thread_id);
111-
} catch (e) {
112-
console.error("Error creating thread", e);
113-
toast({
114-
title: "Error creating thread.",
115-
});
116-
}
117-
return thread;
118-
};
119-
12075
const getOrCreateAssistant = async () => {
12176
const assistantIdCookie = getCookie("clc_py_assistant_id");
12277
if (assistantIdCookie) {
@@ -132,7 +87,7 @@ export function useGraph(userId: string | undefined) {
13287
};
13388

13489
const streamMessage = async (params: GraphInput) => {
135-
if (!threadId) {
90+
if (!inputArgs.threadId) {
13691
toast({
13792
title: "Error",
13893
description: "Thread ID not found",
@@ -166,7 +121,7 @@ export function useGraph(userId: string | undefined) {
166121
}),
167122
};
168123

169-
const stream = client.runs.stream(threadId, assistantId, {
124+
const stream = client.runs.stream(inputArgs.threadId, assistantId, {
170125
input,
171126
streamMode: "events",
172127
config: {
@@ -608,22 +563,24 @@ export function useGraph(userId: string | undefined) {
608563
if (runId) {
609564
// Chain `.then` to not block the stream
610565
shareRun(runId).then((sharedRunURL) => {
611-
setMessages((prevMessages) => {
612-
const langSmithToolCallMessage = new AIMessage({
613-
content: "",
614-
id: uuidv4(),
615-
tool_calls: [
616-
{
617-
name: "langsmith_tool_ui",
618-
args: { sharedRunURL },
619-
id: sharedRunURL
620-
?.split("https://smith.langchain.com/public/")[1]
621-
.split("/")[0],
622-
},
623-
],
566+
if (sharedRunURL) {
567+
setMessages((prevMessages) => {
568+
const langSmithToolCallMessage = new AIMessage({
569+
content: "",
570+
id: uuidv4(),
571+
tool_calls: [
572+
{
573+
name: "langsmith_tool_ui",
574+
args: { sharedRunURL },
575+
id: sharedRunURL
576+
?.split("https://smith.langchain.com/public/")[1]
577+
.split("/")[0],
578+
},
579+
],
580+
});
581+
return [...prevMessages, langSmithToolCallMessage];
624582
});
625-
return [...prevMessages, langSmithToolCallMessage];
626-
});
583+
}
627584
});
628585
}
629586
};
@@ -725,12 +682,10 @@ export function useGraph(userId: string | undefined) {
725682
return {
726683
messages,
727684
assistantId,
728-
threadId,
729685
selectedModel,
730686
setSelectedModel,
731687
setMessages,
732688
streamMessage,
733-
createThread,
734689
switchSelectedThread,
735690
};
736691
}

0 commit comments

Comments
 (0)