Skip to content

Commit

Permalink
merge the v0.1.0 from the forked version to agiresearch (#292)
Browse files Browse the repository at this point in the history
* 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
dongyuanjushi and BRama10 authored Nov 1, 2024
1 parent c077422 commit 9f13013
Show file tree
Hide file tree
Showing 22 changed files with 2,611 additions and 166 deletions.
204 changes: 204 additions & 0 deletions agenthub/app/agentchat/page.tsx
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., &quot;, &amp;)
parsed = parsed.replace(/&quot;/g, '"')
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&#39;/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;
28 changes: 18 additions & 10 deletions agenthub/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ import '@/styles/google-font-Source-Sans-Pro.css'
import '@/styles/google-font-IBM-Plex-Mono.css'
import "./globals.css";
import "./ts.css"
import '@mantine/core/styles.css';

import { ColorSchemeScript, MantineProvider } from '@mantine/core';

export const metadata: Metadata = {
title: 'AIOS – The future of AI Agents',
Expand Down Expand Up @@ -72,18 +75,23 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<link rel="alternate" type="application/rss+xml" href="/blog/feed.xml" title="Hugging Face Blog" />
<script defer data-domain="huggingface.co" src="/js/script.js"></script>
</Head> */}
<head>
<ColorSchemeScript />
</head>
<body>
<Providers>
<main
className="HomePage flex min-h-screen flex-col text-black bg-white dark:bg-gray-950"
style={{ fontSize: 16 }}
>
<div className="flex min-h-screen flex-col">
<NavHeader />
{/* <div className='w-full bg-inherit opacity-0 h-[24px]'></div> */}
{children}
</div>
</main>
<MantineProvider>
<main
className="HomePage flex min-h-screen flex-col text-black bg-white dark:bg-gray-950"
style={{ fontSize: 16 }}
>
<div className="flex min-h-screen flex-col">
{/* <NavHeader /> */}
{/* <div className='w-full bg-inherit opacity-0 h-[24px]'></div> */}
{children}
</div>
</main>
</MantineProvider>
</Providers>
</body>
</html>
Expand Down
31 changes: 31 additions & 0 deletions agenthub/components/agentchat/Header.tsx
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>
);
};
Loading

0 comments on commit 9f13013

Please sign in to comment.