Skip to content

Commit 97888e0

Browse files
committed
feat: add generated thread names
Signed-off-by: tylerslaton <[email protected]>
1 parent 161cfbb commit 97888e0

File tree

4 files changed

+36
-8
lines changed

4 files changed

+36
-8
lines changed

actions/threads.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use server"
22

33
import { THREADS_DIR } from "@/config/env";
4+
import { gpt } from "@/config/env";
45
import fs from "fs/promises";
56
import path from 'path';
67

@@ -74,7 +75,14 @@ async function newThreadName(): Promise<string> {
7475
return `New Thread${threads.length ? ' ' + (threads.length+1): '' }`;
7576
}
7677

77-
export async function createThread(script: string): Promise<Thread> {
78+
export async function generateThreadName(firstMessage: string): Promise<string> {
79+
const summary = await gpt().evaluate({
80+
instructions: `Summarize the following message with a descriptive but brief thread name: ${firstMessage}`
81+
})
82+
return summary.text();
83+
}
84+
85+
export async function createThread(script: string, firstMessage?: string): Promise<Thread> {
7886
const threadsDir = THREADS_DIR();
7987
script = script.replace('.gpt', '');
8088

@@ -96,6 +104,11 @@ export async function createThread(script: string): Promise<Thread> {
96104
await fs.writeFile(path.join(threadPath, META_FILE), JSON.stringify(threadMeta));
97105
await fs.writeFile(path.join(threadPath, STATE_FILE), '');
98106

107+
if (firstMessage) {
108+
const generatedThreadName = await generateThreadName(firstMessage)
109+
renameThread(id, generatedThreadName);
110+
}
111+
99112
return {
100113
state: threadState,
101114
meta: threadMeta,

components/script.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import useChatSocket from '@/components/script/useChatSocket';
1010
import { Button } from "@nextui-org/react";
1111
import { fetchScript, path } from "@/actions/scripts/fetch";
1212
import { getWorkspaceDir } from "@/actions/workspace";
13-
import { createThread, getThreads, Thread } from "@/actions/threads";
13+
import { createThread, getThreads, generateThreadName, renameThread, Thread } from "@/actions/threads";
1414
import debounce from "lodash/debounce";
15-
import { set } from "lodash";
1615

1716
interface ScriptProps {
1817
file: string;
@@ -37,6 +36,12 @@ const Script: React.FC<ScriptProps> = ({ file, thread, setThreads, className, me
3736
socket, connected, running, messages, setMessages, restart, interrupt, generating, error
3837
} = useChatSocket(isEmpty);
3938

39+
const fetchThreads = async () => {
40+
if (!setThreads) return;
41+
const threads = await getThreads();
42+
setThreads(threads);
43+
};
44+
4045
useEffect(() => {
4146
setHasParams(tool.arguments?.properties != undefined && Object.keys(tool.arguments?.properties).length > 0);
4247
setIsEmpty(!tool.instructions);
@@ -98,14 +103,21 @@ const Script: React.FC<ScriptProps> = ({ file, thread, setThreads, className, me
98103

99104
let threadId = "";
100105
if (hasNoUserMessages() && enableThreads && !thread && setThreads && setSelectedThreadId) {
101-
const newThread = await createThread(file)
106+
const newThread = await createThread(file, message)
102107
threadId = newThread?.meta?.id;
103108
setThreads( await getThreads());
104109
setSelectedThreadId(threadId);
105110
}
106111

112+
107113
setMessages((prevMessages) => [...prevMessages, { type: MessageType.User, message }]);
108114
socket.emit("userMessage", message, threadId);
115+
116+
if (hasNoUserMessages() && thread) {
117+
renameThread(thread, await generateThreadName(message));
118+
fetchThreads();
119+
}
120+
109121
};
110122

111123
const restartScript = useCallback(

components/threads.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const Threads: React.FC<ThreadsProps> = ({ className, setThread, threads, setThr
3434
const isSelected = (id: string) => id === selectedThreadId;
3535

3636
return (
37-
<div className={`relative p-4 ${isCollapsed ? "border-none" : "border-r-1 dark:border-r-zinc-800"}`}>
37+
<div className={`relative p-4 overflow-y-auto ${isCollapsed ? "border-none" : "border-r-1 dark:border-r-zinc-800"}`}>
3838
<div className={`flex justify-between items-center mb-2`}>
3939
<Tooltip content={isCollapsed ? "Expand threads" : "Collapse threads"} placement="top" closeDelay={0.5} radius='full'>
4040
<Button

components/threads/menu.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useState } from "react";
12
import { Popover, PopoverTrigger, PopoverContent, Button, Menu, MenuItem } from "@nextui-org/react";
23
import { deleteThread, renameThread, Thread } from '@/actions/threads';
34
import { GoPencil, GoTrash, GoKebabHorizontal } from "react-icons/go";
@@ -9,6 +10,8 @@ interface NewThreadProps {
910
}
1011

1112
const NewThread = ({ className, threadId, setThreads }: NewThreadProps) => {
13+
const [isOpen, setIsOpen] = useState(false);
14+
1215
const handleDeleteThread = () => {
1316
deleteThread(threadId).then(() => {
1417
setThreads((threads: Thread[]) => threads.filter((thread: Thread) => thread.meta.id !== threadId));
@@ -30,14 +33,14 @@ const NewThread = ({ className, threadId, setThreads }: NewThreadProps) => {
3033
}
3134

3235
return (
33-
<Popover placement="right">
36+
<Popover placement="right" isOpen={isOpen} onOpenChange={(open)=> setIsOpen(open)}>
3437
<PopoverTrigger>
3538
<Button variant="light" radius="full" className={`${className}`} isIconOnly startContent={<GoKebabHorizontal />}/>
3639
</PopoverTrigger>
3740
<PopoverContent className="">
3841
<Menu aria-label="options">
39-
<MenuItem className="py-2" content="Rename" startContent={<GoPencil />} onClick={() => { handleRenameThread() }}>Rename</MenuItem>
40-
<MenuItem aria-label="delete" className="py-2" content="Delete" startContent={<GoTrash />} onClick={() => { handleDeleteThread() }}>Delete</MenuItem>
42+
<MenuItem className="py-2" content="Rename" startContent={<GoPencil />} onClick={() => { setIsOpen(false); handleRenameThread() }}>Rename</MenuItem>
43+
<MenuItem aria-label="delete" className="py-2" content="Delete" startContent={<GoTrash />} onClick={() => { setIsOpen(false); handleDeleteThread()}}>Delete</MenuItem>
4144
</Menu>
4245
</PopoverContent>
4346
</Popover>

0 commit comments

Comments
 (0)