Skip to content

Commit 019ddb2

Browse files
authored
Fix: Move knowledge location for thread, delete dataset after thread deletion (#360)
Signed-off-by: Daishan Peng <[email protected]>
1 parent ababb4a commit 019ddb2

File tree

4 files changed

+101
-84
lines changed

4 files changed

+101
-84
lines changed

actions/knowledge/knowledge.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export async function ingest(
1515
if (!datasetID) {
1616
throw new Error('Dataset ID is required');
1717
}
18-
const dir = path.join(workspace, 'knowledge');
18+
const dir = path.join(path.dirname(workspace), 'knowledge');
1919
const knowledgeBinaryPath = process.env.KNOWLEDGE_BIN;
2020
await execPromise(
2121
`${knowledgeBinaryPath} ingest --prune --dataset ${datasetID} ${dir.replace(/ /g, '\\ ')}`,

actions/threads.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
import { THREADS_DIR, WORKSPACE_DIR } from '@/config/env';
44
import { gpt } from '@/config/env';
55
import fs from 'fs/promises';
6+
import { existsSync } from 'fs';
67
import path from 'path';
8+
import { promisify } from 'util';
9+
import { exec } from 'child_process';
710

811
const STATE_FILE = 'state.json';
912
const META_FILE = 'meta.json';
1013

14+
const execPromise = promisify(exec);
15+
1116
export type Thread = {
1217
state: string;
1318
meta: ThreadMeta;
@@ -131,6 +136,9 @@ export async function createThread(
131136
export async function deleteThread(id: string) {
132137
const threadsDir = THREADS_DIR();
133138
const threadPath = path.join(threadsDir, id);
139+
if (existsSync(path.join(threadPath, 'knowledge'))) {
140+
await execPromise(`${process.env.KNOWLEDGE_BIN} delete-dataset ${id}`);
141+
}
134142
await fs.rm(threadPath, { recursive: true });
135143
}
136144

actions/upload.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export async function uploadFile(
1111
isKnowledge?: boolean
1212
) {
1313
if (isKnowledge) {
14-
workspace = path.join(workspace, 'knowledge');
14+
workspace = path.join(path.dirname(workspace), 'knowledge');
1515
}
1616
const file = formData.get('file') as File;
1717
await fs.mkdir(workspace, { recursive: true });
@@ -32,11 +32,11 @@ export async function deleteFile(path: string) {
3232
}
3333

3434
export async function lsKnowledgeFiles(workspace: string): Promise<string> {
35-
return lsFiles(path.join(workspace, 'knowledge'));
35+
return lsFiles(path.join(path.dirname(workspace), 'knowledge'));
3636
}
3737

3838
export async function deleteKnowledgeFile(workspace: string, name: string) {
39-
return deleteFile(path.join(workspace, 'knowledge', name));
39+
return deleteFile(path.join(path.dirname(workspace), 'knowledge', name));
4040
}
4141

4242
export async function lsFiles(dir: string): Promise<string> {

components/threads/menu.tsx

Lines changed: 89 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
ModalHeader,
1313
ModalFooter,
1414
ModalBody,
15+
Spinner,
1516
} from '@nextui-org/react';
1617
import { deleteThread, renameThread, Thread } from '@/actions/threads';
1718
import { GoPencil, GoTrash, GoKebabHorizontal } from 'react-icons/go';
@@ -27,14 +28,16 @@ const NewThread = ({ className, thread }: NewThreadProps) => {
2728
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
2829
const { isOpen, onOpen, onClose } = useDisclosure();
2930
const { setThreads } = useContext(ChatContext);
31+
const [isLoading, setIsLoading] = useState(false);
3032
const [threadNameInput, setThreadNameInput] = useState('');
3133

32-
const handleDeleteThread = () => {
33-
deleteThread(thread).then(() => {
34-
setThreads((threads: Thread[]) =>
35-
threads.filter((t: Thread) => t.meta.id !== thread)
36-
);
37-
});
34+
const handleDeleteThread = async () => {
35+
setIsLoading(true);
36+
await deleteThread(thread);
37+
setThreads((threads: Thread[]) =>
38+
threads.filter((t: Thread) => t.meta.id !== thread)
39+
);
40+
setIsLoading(false);
3841
};
3942

4043
const handleRenameThread = (newName: string) => {
@@ -54,80 +57,86 @@ const NewThread = ({ className, thread }: NewThreadProps) => {
5457

5558
return (
5659
<>
57-
<Popover
58-
placement="right-start"
59-
isOpen={isPopoverOpen}
60-
onOpenChange={(open) => setIsPopoverOpen(open)}
61-
>
62-
<PopoverTrigger>
63-
<Button
64-
variant="light"
65-
radius="full"
66-
className={`${className}`}
67-
isIconOnly
68-
startContent={<GoKebabHorizontal />}
69-
/>
70-
</PopoverTrigger>
71-
<PopoverContent className="">
72-
<Menu aria-label="options">
73-
<MenuItem
74-
className="py-2"
75-
content="Rename"
76-
startContent={<GoPencil />}
77-
onClick={() => {
78-
setIsPopoverOpen(false);
79-
onOpen();
80-
}}
81-
>
82-
Rename
83-
</MenuItem>
84-
<MenuItem
85-
aria-label="delete"
86-
className="py-2"
87-
content="Delete"
88-
startContent={<GoTrash />}
89-
onClick={() => {
90-
setIsPopoverOpen(false);
91-
handleDeleteThread();
92-
}}
93-
>
94-
Delete
95-
</MenuItem>
96-
</Menu>
97-
</PopoverContent>
98-
</Popover>
99-
<Modal
100-
backdrop={'opaque'}
101-
isOpen={isOpen}
102-
onClose={onClose}
103-
placement="top-center"
104-
>
105-
<ModalContent>
106-
<ModalHeader className="flex flex-col gap-1">
107-
Rename thread
108-
</ModalHeader>
109-
<ModalBody>
110-
<Input
111-
aria-label="rename"
112-
label="New Name"
113-
value={threadNameInput}
114-
onChange={(e) => setThreadNameInput(e.target.value)}
115-
/>
116-
</ModalBody>
117-
<ModalFooter>
118-
<Button
119-
aria-label="rename"
120-
color="primary"
121-
onPress={() => {
122-
handleRenameThread(threadNameInput);
123-
onClose();
124-
}}
125-
>
126-
Rename
127-
</Button>
128-
</ModalFooter>
129-
</ModalContent>
130-
</Modal>
60+
{isLoading ? (
61+
<Spinner color="success" />
62+
) : (
63+
<>
64+
<Popover
65+
placement="right-start"
66+
isOpen={isPopoverOpen}
67+
onOpenChange={(open) => setIsPopoverOpen(open)}
68+
>
69+
<PopoverTrigger>
70+
<Button
71+
variant="light"
72+
radius="full"
73+
className={`${className}`}
74+
isIconOnly
75+
startContent={<GoKebabHorizontal />}
76+
/>
77+
</PopoverTrigger>
78+
<PopoverContent className="">
79+
<Menu aria-label="options">
80+
<MenuItem
81+
className="py-2"
82+
content="Rename"
83+
startContent={<GoPencil />}
84+
onClick={() => {
85+
setIsPopoverOpen(false);
86+
onOpen();
87+
}}
88+
>
89+
Rename
90+
</MenuItem>
91+
<MenuItem
92+
aria-label="delete"
93+
className="py-2"
94+
content="Delete"
95+
startContent={<GoTrash />}
96+
onClick={() => {
97+
setIsPopoverOpen(false);
98+
handleDeleteThread();
99+
}}
100+
>
101+
Delete
102+
</MenuItem>
103+
</Menu>
104+
</PopoverContent>
105+
</Popover>
106+
<Modal
107+
backdrop={'opaque'}
108+
isOpen={isOpen}
109+
onClose={onClose}
110+
placement="top-center"
111+
>
112+
<ModalContent>
113+
<ModalHeader className="flex flex-col gap-1">
114+
Rename thread
115+
</ModalHeader>
116+
<ModalBody>
117+
<Input
118+
aria-label="rename"
119+
label="New Name"
120+
value={threadNameInput}
121+
onChange={(e) => setThreadNameInput(e.target.value)}
122+
/>
123+
</ModalBody>
124+
<ModalFooter>
125+
<Button
126+
aria-label="rename"
127+
color="primary"
128+
onPress={() => {
129+
handleRenameThread(threadNameInput);
130+
onClose();
131+
}}
132+
>
133+
Rename
134+
</Button>
135+
</ModalFooter>
136+
</ModalContent>
137+
</Modal>
138+
</>
139+
)}
131140
</>
132141
);
133142
};

0 commit comments

Comments
 (0)