Commit
·
620331c
1
Parent(s):
b2069e9
fix: Improve error handling and dynamic configuration for HuggingFace OAuth and chat memory
Browse files
src/lib/chat/memory.ts
CHANGED
@@ -57,7 +57,7 @@ export class DexieChatMemory extends BaseChatMessageHistory {
|
|
57 |
const chatModel = CHAT_MODELS.find((m) => m.model === this.config.default_chat_model);
|
58 |
const embeddingModel = EMBEDDING_MODELS.find((m) => m.model === this.config.default_embedding_model);
|
59 |
|
60 |
-
if (!chatModel
|
61 |
throw new Error("Chat or embedding models are not configured.");
|
62 |
}
|
63 |
|
@@ -67,7 +67,7 @@ export class DexieChatMemory extends BaseChatMessageHistory {
|
|
67 |
createdAt: Date.now(),
|
68 |
updatedAt: Date.now(),
|
69 |
model: chatModel.model,
|
70 |
-
embedding_model: embeddingModel
|
71 |
enabled_tools: [],
|
72 |
messages: [],
|
73 |
};
|
|
|
57 |
const chatModel = CHAT_MODELS.find((m) => m.model === this.config.default_chat_model);
|
58 |
const embeddingModel = EMBEDDING_MODELS.find((m) => m.model === this.config.default_embedding_model);
|
59 |
|
60 |
+
if (!chatModel) {
|
61 |
throw new Error("Chat or embedding models are not configured.");
|
62 |
}
|
63 |
|
|
|
67 |
createdAt: Date.now(),
|
68 |
updatedAt: Date.now(),
|
69 |
model: chatModel.model,
|
70 |
+
embedding_model: embeddingModel?.model || '',
|
71 |
enabled_tools: [],
|
72 |
messages: [],
|
73 |
};
|
src/pages/chat/components/Messages.tsx
CHANGED
@@ -23,10 +23,17 @@ export const Messages = React.memo(({
|
|
23 |
const { id } = useParams();
|
24 |
const viewportRef = React.useRef<HTMLDivElement>(null);
|
25 |
const [showScrollToBottom, setShowScrollToBottom] = React.useState(false);
|
|
|
26 |
|
27 |
const handleScroll = React.useCallback((event: Event) => {
|
28 |
const viewport = event.target as HTMLDivElement;
|
29 |
const isNotAtBottom = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight > 10;
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
setShowScrollToBottom(isNotAtBottom);
|
31 |
}, []);
|
32 |
|
@@ -39,6 +46,7 @@ export const Messages = React.memo(({
|
|
39 |
});
|
40 |
}, []);
|
41 |
|
|
|
42 |
React.useEffect(() => {
|
43 |
const viewport = viewportRef.current;
|
44 |
if (!viewport) return;
|
@@ -46,8 +54,76 @@ export const Messages = React.memo(({
|
|
46 |
viewport.addEventListener('scroll', handleScroll);
|
47 |
// Initial check for scroll position
|
48 |
handleScroll({ target: viewport } as unknown as Event);
|
49 |
-
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
if (id === "new" || !messages) {
|
53 |
return <div className="flex-1 min-h-0"><ScrollArea className="h-full" /></div>;
|
@@ -99,7 +175,7 @@ export const Messages = React.memo(({
|
|
99 |
<Button
|
100 |
variant="secondary"
|
101 |
size="icon"
|
102 |
-
className="absolute left-1/2 -translate-x-1/2
|
103 |
onClick={scrollToBottom}
|
104 |
>
|
105 |
<ArrowDown className="h-4 w-4" />
|
|
|
23 |
const { id } = useParams();
|
24 |
const viewportRef = React.useRef<HTMLDivElement>(null);
|
25 |
const [showScrollToBottom, setShowScrollToBottom] = React.useState(false);
|
26 |
+
const initialLoadRef = React.useRef(true);
|
27 |
|
28 |
const handleScroll = React.useCallback((event: Event) => {
|
29 |
const viewport = event.target as HTMLDivElement;
|
30 |
const isNotAtBottom = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight > 10;
|
31 |
+
console.log('Scroll position:', {
|
32 |
+
scrollHeight: viewport.scrollHeight,
|
33 |
+
scrollTop: viewport.scrollTop,
|
34 |
+
clientHeight: viewport.clientHeight,
|
35 |
+
isNotAtBottom
|
36 |
+
});
|
37 |
setShowScrollToBottom(isNotAtBottom);
|
38 |
}, []);
|
39 |
|
|
|
46 |
});
|
47 |
}, []);
|
48 |
|
49 |
+
// Effect for handling scroll events
|
50 |
React.useEffect(() => {
|
51 |
const viewport = viewportRef.current;
|
52 |
if (!viewport) return;
|
|
|
54 |
viewport.addEventListener('scroll', handleScroll);
|
55 |
// Initial check for scroll position
|
56 |
handleScroll({ target: viewport } as unknown as Event);
|
57 |
+
|
58 |
+
// Check scroll position after a short delay to account for content rendering
|
59 |
+
const checkTimeout = setTimeout(() => {
|
60 |
+
handleScroll({ target: viewport } as unknown as Event);
|
61 |
+
}, 100);
|
62 |
+
|
63 |
+
return () => {
|
64 |
+
viewport.removeEventListener('scroll', handleScroll);
|
65 |
+
clearTimeout(checkTimeout);
|
66 |
+
};
|
67 |
+
}, [handleScroll, messages, streamingAIMessageChunks]);
|
68 |
+
|
69 |
+
// Effect for initial scroll to bottom on page load
|
70 |
+
React.useEffect(() => {
|
71 |
+
if (initialLoadRef.current && messages && messages.length > 0 && viewportRef.current) {
|
72 |
+
// Use a timeout to ensure content is rendered before scrolling
|
73 |
+
const initialScrollTimeout = setTimeout(() => {
|
74 |
+
if (viewportRef.current) {
|
75 |
+
viewportRef.current.scrollTo({
|
76 |
+
top: viewportRef.current.scrollHeight,
|
77 |
+
behavior: 'smooth'
|
78 |
+
});
|
79 |
+
initialLoadRef.current = false;
|
80 |
+
}
|
81 |
+
}, 100);
|
82 |
+
|
83 |
+
return () => clearTimeout(initialScrollTimeout);
|
84 |
+
}
|
85 |
+
}, [messages]);
|
86 |
+
|
87 |
+
// Reset initialLoadRef when chat ID changes
|
88 |
+
React.useEffect(() => {
|
89 |
+
// Reset the initial load flag when the chat ID changes
|
90 |
+
initialLoadRef.current = true;
|
91 |
+
|
92 |
+
// Attempt to scroll to bottom after a short delay
|
93 |
+
if (id && id !== "new") {
|
94 |
+
const resetScrollTimeout = setTimeout(() => {
|
95 |
+
if (viewportRef.current && messages && messages.length > 0) {
|
96 |
+
viewportRef.current.scrollTo({
|
97 |
+
top: viewportRef.current.scrollHeight,
|
98 |
+
behavior: 'smooth'
|
99 |
+
});
|
100 |
+
}
|
101 |
+
}, 200);
|
102 |
+
|
103 |
+
return () => clearTimeout(resetScrollTimeout);
|
104 |
+
}
|
105 |
+
}, [id]);
|
106 |
+
|
107 |
+
// Scroll to bottom when streaming messages change
|
108 |
+
React.useEffect(() => {
|
109 |
+
// Only auto-scroll if we're already near the bottom or if this is the first message chunk
|
110 |
+
if (viewportRef.current && streamingAIMessageChunks.length > 0) {
|
111 |
+
const viewport = viewportRef.current;
|
112 |
+
const isNearBottom = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight < 100;
|
113 |
+
|
114 |
+
if (isNearBottom || streamingAIMessageChunks.length === 1) {
|
115 |
+
// Use requestAnimationFrame to ensure smooth scrolling during streaming
|
116 |
+
requestAnimationFrame(() => {
|
117 |
+
if (viewportRef.current) {
|
118 |
+
viewportRef.current.scrollTo({
|
119 |
+
top: viewportRef.current.scrollHeight,
|
120 |
+
behavior: streamingAIMessageChunks.length === 1 ? 'smooth' : 'auto'
|
121 |
+
});
|
122 |
+
}
|
123 |
+
});
|
124 |
+
}
|
125 |
+
}
|
126 |
+
}, [streamingAIMessageChunks]);
|
127 |
|
128 |
if (id === "new" || !messages) {
|
129 |
return <div className="flex-1 min-h-0"><ScrollArea className="h-full" /></div>;
|
|
|
175 |
<Button
|
176 |
variant="secondary"
|
177 |
size="icon"
|
178 |
+
className="absolute z-50 bottom-4 left-1/2 -translate-x-1/2 rounded-full shadow-md hover:bg-accent bg-background/80 backdrop-blur-sm"
|
179 |
onClick={scrollToBottom}
|
180 |
>
|
181 |
<ArrowDown className="h-4 w-4" />
|
src/pages/home/components/Providers.tsx
CHANGED
@@ -24,9 +24,9 @@ export const Providers = ({ config }: ProvidersProps) => {
|
|
24 |
|
25 |
const handleHuggingFaceOAuth = () => {
|
26 |
const clientId = import.meta.env.VITE_HF_CLIENT_ID;
|
27 |
-
const redirectUri =
|
28 |
|
29 |
-
if (!clientId
|
30 |
toast.error("HuggingFace OAuth configuration is missing");
|
31 |
return;
|
32 |
}
|
|
|
24 |
|
25 |
const handleHuggingFaceOAuth = () => {
|
26 |
const clientId = import.meta.env.VITE_HF_CLIENT_ID;
|
27 |
+
const redirectUri = window.location.origin + '/integrations/huggingface-callback';
|
28 |
|
29 |
+
if (!clientId) {
|
30 |
toast.error("HuggingFace OAuth configuration is missing");
|
31 |
return;
|
32 |
}
|
src/pages/integrations/huggingface-callback.tsx
CHANGED
@@ -33,7 +33,7 @@ export function HuggingFaceCallback() {
|
|
33 |
grant_type: "authorization_code",
|
34 |
client_id: import.meta.env.VITE_HF_CLIENT_ID,
|
35 |
client_secret: import.meta.env.VITE_HF_CLIENT_SECRET,
|
36 |
-
redirect_uri:
|
37 |
code,
|
38 |
}),
|
39 |
});
|
|
|
33 |
grant_type: "authorization_code",
|
34 |
client_id: import.meta.env.VITE_HF_CLIENT_ID,
|
35 |
client_secret: import.meta.env.VITE_HF_CLIENT_SECRET,
|
36 |
+
redirect_uri: window.location.origin + '/integrations/huggingface-callback',
|
37 |
code,
|
38 |
}),
|
39 |
});
|