Commit ·
9249538
1
Parent(s): 12621bc
feat: add stop generation functionality and UI improvements
Browse files- package-lock.json +0 -0
- package.json +1 -2
- src/lib/chat/memory.ts +1 -1
- src/pages/chat/components/DocumentBadgesScrollArea.tsx +4 -2
- src/pages/chat/components/Input.tsx +10 -2
- src/pages/chat/components/Messages.tsx +1 -1
- src/pages/chat/page.tsx +6 -0
- src/pages/chat/types.ts +1 -0
package-lock.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
package.json
CHANGED
|
@@ -2,7 +2,6 @@
|
|
| 2 |
"name": "react-vite-ui",
|
| 3 |
"private": true,
|
| 4 |
"version": "0.0.1",
|
| 5 |
-
"homepage": "https://mantrakp04.github.io/sheer",
|
| 6 |
"type": "module",
|
| 7 |
"scripts": {
|
| 8 |
"dev": "vite",
|
|
@@ -51,7 +50,7 @@
|
|
| 51 |
"buffer": "^6.0.3",
|
| 52 |
"class-variance-authority": "^0.7.1",
|
| 53 |
"clsx": "^2.1.1",
|
| 54 |
-
"cmdk": "1.0.
|
| 55 |
"date-fns": "^4.1.0",
|
| 56 |
"dexie": "^4.0.11",
|
| 57 |
"dexie-react-hooks": "^1.1.7",
|
|
|
|
| 2 |
"name": "react-vite-ui",
|
| 3 |
"private": true,
|
| 4 |
"version": "0.0.1",
|
|
|
|
| 5 |
"type": "module",
|
| 6 |
"scripts": {
|
| 7 |
"dev": "vite",
|
|
|
|
| 50 |
"buffer": "^6.0.3",
|
| 51 |
"class-variance-authority": "^0.7.1",
|
| 52 |
"clsx": "^2.1.1",
|
| 53 |
+
"cmdk": "^1.0.4",
|
| 54 |
"date-fns": "^4.1.0",
|
| 55 |
"dexie": "^4.0.11",
|
| 56 |
"dexie-react-hooks": "^1.1.7",
|
src/lib/chat/memory.ts
CHANGED
|
@@ -17,7 +17,7 @@ export class ChatHistoryDB extends Dexie {
|
|
| 17 |
constructor() {
|
| 18 |
super("chat_history");
|
| 19 |
this.version(1).stores({
|
| 20 |
-
sessions: "
|
| 21 |
});
|
| 22 |
}
|
| 23 |
}
|
|
|
|
| 17 |
constructor() {
|
| 18 |
super("chat_history");
|
| 19 |
this.version(1).stores({
|
| 20 |
+
sessions: "id, title, createdAt, updatedAt, model, embedding_model, enabled_tools, messages",
|
| 21 |
});
|
| 22 |
}
|
| 23 |
}
|
src/pages/chat/components/DocumentBadgesScrollArea.tsx
CHANGED
|
@@ -11,6 +11,7 @@ interface DocumentBadgesScrollAreaProps {
|
|
| 11 |
removeable?: boolean;
|
| 12 |
maxHeight?: string;
|
| 13 |
className?: string;
|
|
|
|
| 14 |
}
|
| 15 |
|
| 16 |
export const DocumentBadgesScrollArea = React.memo(({
|
|
@@ -19,10 +20,11 @@ export const DocumentBadgesScrollArea = React.memo(({
|
|
| 19 |
onRemove,
|
| 20 |
removeable = true,
|
| 21 |
maxHeight = "100px",
|
| 22 |
-
className = ""
|
|
|
|
| 23 |
}: DocumentBadgesScrollAreaProps) => (
|
| 24 |
<ScrollArea className={cn("w-full", className)} style={{ maxHeight }}>
|
| 25 |
-
<div className=
|
| 26 |
{documents.map((document) => (
|
| 27 |
<DocumentBadge
|
| 28 |
key={document.id}
|
|
|
|
| 11 |
removeable?: boolean;
|
| 12 |
maxHeight?: string;
|
| 13 |
className?: string;
|
| 14 |
+
rowReverse?: boolean;
|
| 15 |
}
|
| 16 |
|
| 17 |
export const DocumentBadgesScrollArea = React.memo(({
|
|
|
|
| 20 |
onRemove,
|
| 21 |
removeable = true,
|
| 22 |
maxHeight = "100px",
|
| 23 |
+
className = "",
|
| 24 |
+
rowReverse = true,
|
| 25 |
}: DocumentBadgesScrollAreaProps) => (
|
| 26 |
<ScrollArea className={cn("w-full", className)} style={{ maxHeight }}>
|
| 27 |
+
<div className={`flex ${rowReverse ? "flex-row-reverse" : "flex-row"} flex-wrap-reverse gap-1 p-1`}>
|
| 28 |
{documents.map((document) => (
|
| 29 |
<DocumentBadge
|
| 30 |
key={document.id}
|
src/pages/chat/components/Input.tsx
CHANGED
|
@@ -25,6 +25,7 @@ export const Input = React.memo(({
|
|
| 25 |
handleAttachmentRemove,
|
| 26 |
selectedModelName,
|
| 27 |
isGenerating,
|
|
|
|
| 28 |
}: InputProps) => {
|
| 29 |
return (
|
| 30 |
<div className="flex flex-col w-1/2 mx-auto bg-muted rounded-md p-1">
|
|
@@ -34,6 +35,7 @@ export const Input = React.memo(({
|
|
| 34 |
onPreview={setPreviewDocument}
|
| 35 |
onRemove={handleAttachmentRemove}
|
| 36 |
maxHeight="100px"
|
|
|
|
| 37 |
/>
|
| 38 |
)}
|
| 39 |
<AutosizeTextarea
|
|
@@ -70,8 +72,14 @@ export const Input = React.memo(({
|
|
| 70 |
variant="default"
|
| 71 |
size="icon"
|
| 72 |
className="rounded-full"
|
| 73 |
-
onClick={
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
>
|
| 76 |
{isGenerating ? (
|
| 77 |
<Loader2 className="h-4 w-4 animate-spin" />
|
|
|
|
| 25 |
handleAttachmentRemove,
|
| 26 |
selectedModelName,
|
| 27 |
isGenerating,
|
| 28 |
+
stopGenerating,
|
| 29 |
}: InputProps) => {
|
| 30 |
return (
|
| 31 |
<div className="flex flex-col w-1/2 mx-auto bg-muted rounded-md p-1">
|
|
|
|
| 35 |
onPreview={setPreviewDocument}
|
| 36 |
onRemove={handleAttachmentRemove}
|
| 37 |
maxHeight="100px"
|
| 38 |
+
rowReverse={false}
|
| 39 |
/>
|
| 40 |
)}
|
| 41 |
<AutosizeTextarea
|
|
|
|
| 72 |
variant="default"
|
| 73 |
size="icon"
|
| 74 |
className="rounded-full"
|
| 75 |
+
onClick={() => {
|
| 76 |
+
if (isGenerating) {
|
| 77 |
+
// stop the generation
|
| 78 |
+
stopGenerating();
|
| 79 |
+
} else {
|
| 80 |
+
onSendMessage();
|
| 81 |
+
}
|
| 82 |
+
}}
|
| 83 |
>
|
| 84 |
{isGenerating ? (
|
| 85 |
<Loader2 className="h-4 w-4 animate-spin" />
|
src/pages/chat/components/Messages.tsx
CHANGED
|
@@ -99,7 +99,7 @@ export const Messages = React.memo(({
|
|
| 99 |
<Button
|
| 100 |
variant="secondary"
|
| 101 |
size="icon"
|
| 102 |
-
className="absolute left-1/2 -translate-x-1/2 bottom-4 rounded-full shadow-md hover:bg-accent
|
| 103 |
onClick={scrollToBottom}
|
| 104 |
>
|
| 105 |
<ArrowDown className="h-4 w-4" />
|
|
|
|
| 99 |
<Button
|
| 100 |
variant="secondary"
|
| 101 |
size="icon"
|
| 102 |
+
className="absolute left-1/2 -translate-x-1/2 z-50 bottom-4 rounded-full shadow-md hover:bg-accent bg-background/80 backdrop-blur-sm"
|
| 103 |
onClick={scrollToBottom}
|
| 104 |
>
|
| 105 |
<ArrowDown className="h-4 w-4" />
|
src/pages/chat/page.tsx
CHANGED
|
@@ -174,6 +174,11 @@ export function ChatPage() {
|
|
| 174 |
generateMessage(id, content, [], isGenerating, setIsGenerating, setStreamingHumanMessage, setStreamingAIMessageChunks, chatManager, setInput, setAttachments);
|
| 175 |
}, [id, chatSession, isGenerating, chatHistoryDB.sessions, chatManager]);
|
| 176 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
return (
|
| 178 |
<div className="flex flex-col h-screen p-2">
|
| 179 |
<Messages
|
|
@@ -205,6 +210,7 @@ export function ChatPage() {
|
|
| 205 |
handleAttachmentRemove={handleAttachmentRemove}
|
| 206 |
selectedModelName={selectedModelName}
|
| 207 |
isGenerating={isGenerating}
|
|
|
|
| 208 |
/>
|
| 209 |
<FilePreviewDialog
|
| 210 |
document={previewDocument}
|
|
|
|
| 174 |
generateMessage(id, content, [], isGenerating, setIsGenerating, setStreamingHumanMessage, setStreamingAIMessageChunks, chatManager, setInput, setAttachments);
|
| 175 |
}, [id, chatSession, isGenerating, chatHistoryDB.sessions, chatManager]);
|
| 176 |
|
| 177 |
+
const stopGenerating = React.useCallback(() => {
|
| 178 |
+
chatManager.controller.abort();
|
| 179 |
+
setIsGenerating(false);
|
| 180 |
+
}, [chatManager, setIsGenerating]);
|
| 181 |
+
|
| 182 |
return (
|
| 183 |
<div className="flex flex-col h-screen p-2">
|
| 184 |
<Messages
|
|
|
|
| 210 |
handleAttachmentRemove={handleAttachmentRemove}
|
| 211 |
selectedModelName={selectedModelName}
|
| 212 |
isGenerating={isGenerating}
|
| 213 |
+
stopGenerating={stopGenerating}
|
| 214 |
/>
|
| 215 |
<FilePreviewDialog
|
| 216 |
document={previewDocument}
|
src/pages/chat/types.ts
CHANGED
|
@@ -39,6 +39,7 @@ export interface InputProps {
|
|
| 39 |
handleAttachmentFileUpload: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
| 40 |
handleAttachmentUrlUpload: () => void;
|
| 41 |
handleAttachmentRemove: (docId: string) => void;
|
|
|
|
| 42 |
}
|
| 43 |
|
| 44 |
export interface FilePreviewDialogProps {
|
|
|
|
| 39 |
handleAttachmentFileUpload: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
| 40 |
handleAttachmentUrlUpload: () => void;
|
| 41 |
handleAttachmentRemove: (docId: string) => void;
|
| 42 |
+
stopGenerating: () => void;
|
| 43 |
}
|
| 44 |
|
| 45 |
export interface FilePreviewDialogProps {
|