This commit is contained in:
Tong Li 2025-02-07 06:00:09 +00:00 committed by GitHub
commit 7681935395
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 99 additions and 20 deletions

View file

@ -1,17 +1,18 @@
'use client'; 'use client';
import { useEffect, useRef, useState } from 'react'; import {useEffect, useRef, useState} from 'react';
import { Document } from '@langchain/core/documents'; import {Document} from '@langchain/core/documents';
import Navbar from './Navbar'; import Navbar from './Navbar';
import Chat from './Chat'; import Chat from './Chat';
import EmptyChat from './EmptyChat'; import EmptyChat from './EmptyChat';
import crypto from 'crypto'; import crypto from 'crypto';
import { toast } from 'sonner'; import {toast} from 'sonner';
import { useSearchParams } from 'next/navigation'; import {useSearchParams} from 'next/navigation';
import { getSuggestions } from '@/lib/actions'; import {getSuggestions} from '@/lib/actions';
import { Settings } from 'lucide-react'; import {Settings} from 'lucide-react';
import SettingsDialog from './SettingsDialog'; import SettingsDialog from './SettingsDialog';
import NextError from 'next/error'; import NextError from 'next/error';
import {Mcid} from "@/lib/mcid";
export type Message = { export type Message = {
messageId: string; messageId: string;
@ -382,10 +383,10 @@ const loadMessages = async (
setIsMessagesLoaded(true); setIsMessagesLoaded(true);
}; };
const ChatWindow = ({ id }: { id?: string }) => { const ChatWindow = ({id}: { id?: string }) => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const initialMessage = searchParams.get('q'); const initialMessage = searchParams.get('q');
const [userId, setUserId] = useState<string | undefined>();
const [chatId, setChatId] = useState<string | undefined>(id); const [chatId, setChatId] = useState<string | undefined>(id);
const [newChatCreated, setNewChatCreated] = useState(false); const [newChatCreated, setNewChatCreated] = useState(false);
@ -410,6 +411,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
const [focusMode, setFocusMode] = useState('webSearch'); const [focusMode, setFocusMode] = useState('webSearch');
const [optimizationMode, setOptimizationMode] = useState('speed'); const [optimizationMode, setOptimizationMode] = useState('speed');
const [copilotEnabled, setCopilotEnabled] = useState(true);
const [isMessagesLoaded, setIsMessagesLoaded] = useState(false); const [isMessagesLoaded, setIsMessagesLoaded] = useState(false);
@ -417,6 +419,33 @@ const ChatWindow = ({ id }: { id?: string }) => {
const [isSettingsOpen, setIsSettingsOpen] = useState(false); const [isSettingsOpen, setIsSettingsOpen] = useState(false);
useEffect(() => {
const initializeUserId = () => {
try {
// 从 localStorage 读取现有用户 ID
const storedUserId = localStorage.getItem('userId');
if (storedUserId) {
setUserId(storedUserId);
console.debug('Using existing user ID:', storedUserId);
} else {
const newUserId = new Mcid().generate().toString();
localStorage.setItem('userId', newUserId);
setUserId(newUserId);
console.debug('Generated new user ID:', newUserId);
}
} catch (error) {
console.error('Error initializing user ID:', error);
const fallbackId = "1234567890";
localStorage.setItem('userId', fallbackId);
setUserId(fallbackId);
}
};
initializeUserId();
}, []);
useEffect(() => { useEffect(() => {
if ( if (
chatId && chatId &&
@ -437,7 +466,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
} else if (!chatId) { } else if (!chatId) {
setNewChatCreated(true); setNewChatCreated(true);
setIsMessagesLoaded(true); setIsMessagesLoaded(true);
setChatId(crypto.randomBytes(20).toString('hex')); setChatId(new Mcid().generate().toString());
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
@ -465,7 +494,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
} else { } else {
setIsReady(false); setIsReady(false);
} }
}, [isMessagesLoaded, isWSReady]); }, [isMessagesLoaded, isWSReady, userId]);
const sendMessage = async (message: string, messageId?: string) => { const sendMessage = async (message: string, messageId?: string) => {
if (loading) return; if (loading) return;
@ -481,11 +510,12 @@ const ChatWindow = ({ id }: { id?: string }) => {
let recievedMessage = ''; let recievedMessage = '';
let added = false; let added = false;
messageId = messageId ?? crypto.randomBytes(7).toString('hex'); messageId = messageId ?? new Mcid().generate().toString();
ws.send( ws.send(
JSON.stringify({ JSON.stringify({
type: 'message', type: 'message',
userId:userId,
message: { message: {
messageId: messageId, messageId: messageId,
chatId: chatId!, chatId: chatId!,
@ -493,6 +523,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
}, },
files: fileIds, files: fileIds,
focusMode: focusMode, focusMode: focusMode,
copilotEnabled: copilotEnabled,
optimizationMode: optimizationMode, optimizationMode: optimizationMode,
history: [...chatHistory, ['human', message]], history: [...chatHistory, ['human', message]],
}), }),
@ -556,7 +587,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
setMessages((prev) => setMessages((prev) =>
prev.map((message) => { prev.map((message) => {
if (message.messageId === data.messageId) { if (message.messageId === data.messageId) {
return { ...message, content: message.content + data.data }; return {...message, content: message.content + data.data};
} }
return message; return message;
@ -589,7 +620,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
setMessages((prev) => setMessages((prev) =>
prev.map((msg) => { prev.map((msg) => {
if (msg.messageId === lastMsg.messageId) { if (msg.messageId === lastMsg.messageId) {
return { ...msg, suggestions: suggestions }; return {...msg, suggestions: suggestions};
} }
return msg; return msg;
}), }),
@ -639,19 +670,19 @@ const ChatWindow = ({ id }: { id?: string }) => {
Failed to connect to the server. Please try again later. Failed to connect to the server. Please try again later.
</p> </p>
</div> </div>
<SettingsDialog isOpen={isSettingsOpen} setIsOpen={setIsSettingsOpen} /> <SettingsDialog isOpen={isSettingsOpen} setIsOpen={setIsSettingsOpen}/>
</div> </div>
); );
} }
return isReady ? ( return isReady ? (
notFound ? ( notFound ? (
<NextError statusCode={404} /> <NextError statusCode={404}/>
) : ( ) : (
<div> <div>
{messages.length > 0 ? ( {messages.length > 0 ? (
<> <>
<Navbar chatId={chatId!} messages={messages} /> <Navbar chatId={chatId!} messages={messages}/>
<Chat <Chat
loading={loading} loading={loading}
messages={messages} messages={messages}
@ -668,6 +699,8 @@ const ChatWindow = ({ id }: { id?: string }) => {
<EmptyChat <EmptyChat
sendMessage={sendMessage} sendMessage={sendMessage}
focusMode={focusMode} focusMode={focusMode}
copilotEnabled={copilotEnabled}
setCopilotEnabled={setCopilotEnabled}
setFocusMode={setFocusMode} setFocusMode={setFocusMode}
optimizationMode={optimizationMode} optimizationMode={optimizationMode}
setOptimizationMode={setOptimizationMode} setOptimizationMode={setOptimizationMode}

View file

@ -8,6 +8,8 @@ const EmptyChat = ({
sendMessage, sendMessage,
focusMode, focusMode,
setFocusMode, setFocusMode,
copilotEnabled,
setCopilotEnabled,
optimizationMode, optimizationMode,
setOptimizationMode, setOptimizationMode,
fileIds, fileIds,
@ -18,6 +20,8 @@ const EmptyChat = ({
sendMessage: (message: string) => void; sendMessage: (message: string) => void;
focusMode: string; focusMode: string;
setFocusMode: (mode: string) => void; setFocusMode: (mode: string) => void;
copilotEnabled: boolean;
setCopilotEnabled: (enabled: boolean) => void;
optimizationMode: string; optimizationMode: string;
setOptimizationMode: (mode: string) => void; setOptimizationMode: (mode: string) => void;
fileIds: string[]; fileIds: string[];
@ -44,6 +48,8 @@ const EmptyChat = ({
sendMessage={sendMessage} sendMessage={sendMessage}
focusMode={focusMode} focusMode={focusMode}
setFocusMode={setFocusMode} setFocusMode={setFocusMode}
copilotEnabled={copilotEnabled}
setCopilotEnabled={setCopilotEnabled}
optimizationMode={optimizationMode} optimizationMode={optimizationMode}
setOptimizationMode={setOptimizationMode} setOptimizationMode={setOptimizationMode}
fileIds={fileIds} fileIds={fileIds}

View file

@ -11,6 +11,8 @@ const EmptyChatMessageInput = ({
sendMessage, sendMessage,
focusMode, focusMode,
setFocusMode, setFocusMode,
copilotEnabled,
setCopilotEnabled,
optimizationMode, optimizationMode,
setOptimizationMode, setOptimizationMode,
fileIds, fileIds,
@ -23,12 +25,13 @@ const EmptyChatMessageInput = ({
setFocusMode: (mode: string) => void; setFocusMode: (mode: string) => void;
optimizationMode: string; optimizationMode: string;
setOptimizationMode: (mode: string) => void; setOptimizationMode: (mode: string) => void;
copilotEnabled:boolean
setCopilotEnabled:(mode: boolean) => void;
fileIds: string[]; fileIds: string[];
setFileIds: (fileIds: string[]) => void; setFileIds: (fileIds: string[]) => void;
files: File[]; files: File[];
setFiles: (files: File[]) => void; setFiles: (files: File[]) => void;
}) => { }) => {
const [copilotEnabled, setCopilotEnabled] = useState(false);
const [message, setMessage] = useState(''); const [message, setMessage] = useState('');
const inputRef = useRef<HTMLTextAreaElement | null>(null); const inputRef = useRef<HTMLTextAreaElement | null>(null);
@ -94,6 +97,7 @@ const EmptyChatMessageInput = ({
/> />
</div> </div>
<div className="flex flex-row items-center space-x-1 sm:space-x-4"> <div className="flex flex-row items-center space-x-1 sm:space-x-4">
<CopilotToggle setCopilotEnabled={setCopilotEnabled} copilotEnabled={copilotEnabled}/>
<Optimization <Optimization
optimizationMode={optimizationMode} optimizationMode={optimizationMode}
setOptimizationMode={setOptimizationMode} setOptimizationMode={setOptimizationMode}

View file

@ -7,7 +7,7 @@ const ThemeProviderComponent = ({
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
return ( return (
<ThemeProvider attribute="class" enableSystem={false} defaultTheme="dark"> <ThemeProvider attribute="class" enableSystem={false} defaultTheme="light">
{children} {children}
</ThemeProvider> </ThemeProvider>
); );

36
ui/lib/mcid.ts Normal file
View file

@ -0,0 +1,36 @@
// utils/mcid.ts
export class Mcid {
private lastTimestamp = -1;
private sequence = 0;
constructor(private readonly machineId: number = 0) {
if (machineId < 0 || machineId > 255) {
throw new Error('Machine ID must be between 0 and 255');
}
}
generate(): number {
let now = Date.now();
if (now < this.lastTimestamp) {
throw new Error('Clock moved backwards');
}
if (now === this.lastTimestamp) {
this.sequence = (this.sequence + 1) & 0xf;
if (this.sequence === 0) {
while (now <= this.lastTimestamp) {
now = Date.now();
}
}
} else {
this.sequence = 0;
}
this.lastTimestamp = now;
return (
(now * 0x1000) + (this.machineId * 16) + this.sequence
);
}
}