-
Notifications
You must be signed in to change notification settings - Fork 410
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
merge the v0.1.0 from the forked version to agiresearch (#292)
* refactor agent query message * update query response format * update * update agents * update test files * update response listener with event singal * add linux installer * feat: add installer and update docs * add configuration file * update installation script * update docs * rm unused installation script * update agents * Agent UI v1.5 (#6) --------- Co-authored-by: Balaji R <[email protected]>
- Loading branch information
1 parent
c077422
commit 9f13013
Showing
22 changed files
with
2,611 additions
and
166 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
'use client' | ||
|
||
import React, { useState, useRef, useEffect } from 'react'; | ||
import { ChatEditor } from '@/components/chat/editor/Editor'; | ||
import { useMounted } from '@/lib/mounted'; | ||
|
||
import { Message, Chat } from '@/interfaces/agentchat'; | ||
import { Sidebar } from '@/components/agentchat/Sidebar'; | ||
import { Header } from '@/components/agentchat/Header'; | ||
import { MessageList } from '@/components/agentchat/MessageList'; | ||
import axios from 'axios'; | ||
import { AgentCommand } from '@/components/chat/body/message-box'; | ||
import { baseUrl, serverUrl } from '@/lib/env'; | ||
|
||
|
||
|
||
const updateChatName = (chatId: number, newName: string) => { | ||
// setChats(prevChats => | ||
// prevChats.map(chat => | ||
// chat.id === chatId ? { ...chat, name: newName } : chat | ||
// ) | ||
// ); | ||
}; | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
const ChatInterface: React.FC = () => { | ||
const [messages, setMessages] = useState<Message[]>([]); | ||
const [darkMode, setDarkMode] = useState<boolean>(false); | ||
const [chats, setChats] = useState<Chat[]>([{ id: 1, name: 'General' }]); | ||
const [activeChat, setActiveChat] = useState<number>(1); | ||
const messagesEndRef = useRef<HTMLDivElement>(null); | ||
|
||
function parseText(input: string): string { | ||
// Step 1: Replace mention spans with the custom format | ||
let parsed = input.replace(/<span class="mention" data-type="mention" data-id="([^"]+)">@[^<]+<\/span>/g, '?>>$1/?>>'); | ||
|
||
// Step 2: Convert <br> tags to newlines | ||
parsed = parsed.replace(/<br[^>]*>/g, '\n'); | ||
|
||
// Step 3: Remove all remaining HTML tags | ||
parsed = parsed.replace(/<[^>]+>/g, ''); | ||
|
||
// Decode HTML entities (e.g., ", &) | ||
parsed = parsed.replace(/"/g, '"') | ||
.replace(/&/g, '&') | ||
.replace(/</g, '<') | ||
.replace(/>/g, '>') | ||
.replace(/'/g, "'"); | ||
|
||
return parsed.trim(); | ||
} | ||
|
||
interface MessageBundle { | ||
name: string; | ||
content: string; | ||
} | ||
|
||
|
||
function parseNamedContent(inputString: string) { | ||
// Regular expression to match the pattern ?>>Name/?>>\s*Content | ||
const regex = /\?>>(.*?)\/?>>([^?]*)/g; | ||
const results = []; | ||
|
||
// Find all matches | ||
let match; | ||
while ((match = regex.exec(inputString)) !== null) { | ||
// Extract name and content, trim whitespace | ||
const name = match[1].trim().slice(0, -2); | ||
// Preserve newlines in content but trim surrounding whitespace | ||
const content = match[2].replace(/^\s+|\s+$/g, ''); | ||
|
||
results.push({ | ||
name, | ||
content | ||
}); | ||
} | ||
|
||
return results; | ||
} | ||
|
||
// Ex | ||
|
||
|
||
useEffect(() => { | ||
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); | ||
}, [messages]); | ||
|
||
const handleSend = async (content: string, attachments: File[]) => { | ||
if (content.trim() || attachments.length > 0) { | ||
const newMessage: Message = { | ||
id: Date.now(), | ||
text: content, | ||
sender: 'user', | ||
timestamp: new Date(), | ||
attachments: attachments.map(file => file.name), | ||
thinking: false | ||
}; | ||
setMessages([...messages, newMessage]); | ||
|
||
let messageId = Date.now(); | ||
|
||
// Handle file uploads here (e.g., to a server) | ||
const botMessage: Message = { | ||
id: messageId, | ||
text: ``, | ||
sender: 'bot', | ||
timestamp: new Date(), | ||
thinking: true | ||
}; | ||
|
||
setMessages(prevMessages => [...prevMessages, botMessage]); | ||
|
||
const res = await _(parseNamedContent(parseText(content))[0] as AgentCommand) | ||
|
||
setMessages(prevMessages => [...prevMessages].map(message => { | ||
if (message.id == messageId) { | ||
return { ...message, thinking: false }; | ||
} | ||
return res.content; | ||
})); | ||
} | ||
}; | ||
|
||
const addChat = () => { | ||
const newChat: Chat = { id: Date.now(), name: `Chat ${chats.length + 1}` }; | ||
setChats([...chats, newChat]); | ||
setActiveChat(newChat.id); | ||
}; | ||
|
||
const _ = async (command: AgentCommand) => { | ||
const addAgentResponse = await axios.post(`${baseUrl}/api/proxy`, { | ||
type: 'POST', | ||
url: `${serverUrl}/add_agent`, | ||
payload: { | ||
agent_name: command.name, | ||
task_input: command.content, | ||
} | ||
}); | ||
|
||
console.log(addAgentResponse.data); | ||
|
||
// Wait for 1050ms | ||
await new Promise(resolve => setTimeout(resolve, 1050)); | ||
|
||
let recent_response: any; | ||
|
||
try { | ||
// Second request: Execute agent | ||
const executeAgentResponse = await axios.post(`${baseUrl}/api/proxy`, { | ||
type: 'GET', | ||
url: `${serverUrl}/execute_agent?pid=${addAgentResponse.data.pid}`, | ||
}); | ||
|
||
console.log(executeAgentResponse.data); | ||
recent_response = executeAgentResponse.data.response.result.content; | ||
|
||
if (typeof recent_response !== 'string') { | ||
recent_response = "Agent Had Difficulty Thinking" | ||
} | ||
} catch (e) { | ||
recent_response = "Agent Had Difficulty Thinking" | ||
} | ||
|
||
|
||
//return recent_response | ||
return { | ||
name: command.name, | ||
content: recent_response | ||
}; | ||
} | ||
|
||
const mounted = useMounted(); | ||
|
||
return ( | ||
<div className={`flex h-screen ${darkMode ? 'bg-gray-900' : 'bg-gray-50'}`}> | ||
<Sidebar | ||
chats={chats} | ||
activeChat={activeChat} | ||
setActiveChat={setActiveChat} | ||
addChat={addChat} | ||
updateChatName={updateChatName} | ||
darkMode={darkMode} | ||
/> | ||
<div className="flex flex-col flex-grow pb-4"> | ||
<Header darkMode={darkMode} setDarkMode={setDarkMode} /> | ||
<MessageList messages={messages} darkMode={darkMode} /> | ||
<div className='w-full flex h-fit justify-center'> | ||
{mounted && <ChatEditor onSend={handleSend} darkMode={darkMode} />} | ||
</div> | ||
|
||
<div ref={messagesEndRef} /> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
|
||
export default ChatInterface; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React from 'react'; | ||
|
||
import { Switch, useMantineTheme } from '@mantine/core'; | ||
import { Sun, Moon, Hash } from 'lucide-react'; | ||
|
||
export interface HeaderProps { | ||
darkMode: boolean; | ||
setDarkMode: React.Dispatch<React.SetStateAction<boolean>>; | ||
} | ||
|
||
export const Header: React.FC<HeaderProps> = ({ darkMode, setDarkMode }) => { | ||
const theme = useMantineTheme(); | ||
return ( | ||
<div className={`flex justify-between items-center p-3 border-b ${darkMode ? 'bg-gray-900 text-white border-gray-800' : 'bg-white text-black border-gray-200'}`}> | ||
<div className="flex items-center space-x-2"> | ||
<Hash size={20} className="text-gray-500" /> | ||
<h1 className="text-lg font-medium">General</h1> | ||
</div> | ||
<div className="flex items-center space-x-2"> | ||
<Sun size={16} className={darkMode ? 'text-gray-400' : 'text-yellow-500'} /> | ||
<Switch | ||
checked={darkMode} | ||
onChange={(event) => setDarkMode(event.currentTarget.checked)} | ||
size="sm" | ||
color={theme.primaryColor} | ||
/> | ||
<Moon size={16} className={darkMode ? 'text-blue-400' : 'text-gray-400'} /> | ||
</div> | ||
</div> | ||
); | ||
}; |
Oops, something went wrong.