浏览代码

mentions list

BRama10 12 小时之前
父节点
当前提交
26f16b3170

+ 175 - 94
agenthub/app/agentchat/page.tsx

@@ -8,115 +8,196 @@ 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
-    //   )
-    // );
-  };
+  // 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);
-
-    useEffect(() => {
-        messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
-      }, [messages]);
-
-    const handleSend = (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]);
-
-            // Handle file uploads here (e.g., to a server)
-            const botMessage: Message = {
-                id: 3,
-                text: `Here's a sample response with Markdown:
-
-# Heading 1
-## Heading 2
-
-- List item 1
-- List item 2
-
-\`\`\`python
-def greet(name):
-  print(f"Hello, {name}!")
-
-greet("World")
-\`\`\`
-
-> This is a blockquote.
-
-**Bold text** and *italic text*.`,
-                sender: 'bot',
-                timestamp: new Date(),
-                thinking: true
-            };
-            setMessages(prevMessages => [...prevMessages, botMessage]);
-
-            setTimeout(() => {
-                setMessages(prevMessages => [...prevMessages].map(message => {
-                    if (message.id == 3) {
-                        return { ...message, thinking: false };
-                    }
-                    return message;
-                }));
-            }, 3000);
+  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 addChat = () => {
+    const newChat: Chat = { id: Date.now(), name: `Chat ${chats.length + 1}` };
+    setChats([...chats, newChat]);
+    setActiveChat(newChat.id);
+  };
 
-    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>
+  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>
+  );
 };
 
 

+ 16 - 0
agenthub/components/chat/editor/Editor.tsx

@@ -12,6 +12,8 @@ import { ActionIcon, Group, Paper, Text as MantineText, useMantineTheme, ScrollA
 import { Send, Plus, X, FileIcon } from 'lucide-react';
 
 import suggestion from './Suggestion'
+import { baseUrl, serverUrl } from '@/lib/env';
+import axios from 'axios';
 
 export interface ChatEditorProps {
   onSend: (content: string, attachments: File[]) => void;
@@ -26,6 +28,20 @@ export const ChatEditor: React.FC<ChatEditorProps> = ({ onSend, darkMode }) => {
   const [hoverIndex, setHoverIndex] = useState<number | null>(null);
   const fileInputRef = useRef<HTMLInputElement>(null);
   const theme = useMantineTheme();
+  const [agents, setAgents] = useState([]);
+
+  useEffect(() => {
+
+
+    const _ = async () => {
+      const response = await axios.post(`${baseUrl}/api/proxy`, {
+          type: 'GET',
+          url: `${serverUrl}/get_all_agents`,
+      });
+      setAgents(response.data.agents)
+  }
+  _()
+  }, [])
 
   let currentStyleElement: HTMLStyleElement | null = null;
 

+ 1 - 0
agenthub/components/chat/editor/MentionListV2.tsx

@@ -23,6 +23,7 @@ export default forwardRef((props: any, ref: any) => {
   }
 
   const enterHandler = (e: any) => {
+    e.stopImmediatePropagation();
     e.preventDefault();
     e.stopPropagation();
     selectItem(selectedIndex)

+ 49 - 41
agenthub/public/MentionListV2Dark.scss

@@ -1,47 +1,55 @@
 /* Dropdown menu */
 .dropdown-menu {
-    background: rgb(31, 41, 55);
-    border: 1px solid var(--gray-4);
-    border-radius: 0.7rem;
-    box-shadow: var(--shadow);
+  background: rgb(31, 41, 55);
+  border: 1px solid var(--gray-4);
+  border-radius: 0.7rem;
+  box-shadow: var(--shadow);
+  display: flex;
+  flex-direction: column;
+  gap: 0.1rem;
+  overflow: auto;
+  padding: 0.4rem;
+  position: relative;
+  color: var(--white);
+
+  button {
+    align-items: center;
+    background-color: transparent;
     display: flex;
-    flex-direction: column;
-    gap: 0.1rem;
-    overflow: auto;
-    padding: 0.4rem;
-    position: relative;
-    color: var(--white);
-  
-    button {
-      align-items: center;
-      background-color: transparent;
-      display: flex; 
-      gap: 0.25rem;
-      text-align: left;
-      width: 100%;
-  
-      &:hover,
-      &:hover.is-selected {
-        background-color: #ccc6c631;
-      }
-  
-      &.is-selected {
-        background-color: #ccc6c631;
-      }
-    }
-  }
+    gap: 0.25rem;
+    text-align: left;
+    width: 100%;
 
-  .tiptap {
-    :first-child {
-      margin-top: 0;
+    &:hover,
+    &:hover.is-selected {
+      background-color: #ccc6c631;
     }
-  
-    .mention {
-      background-color: var(--purple-light-dark);
-      border-radius: 0.4rem;
-      box-decoration-break: clone;
-      color: var(--white);
-      // font-weight: 600;
-      padding: 0.1rem 0.3rem;
+
+    &.is-selected {
+      background-color: #ccc6c631;
     }
-  }
+  }
+}
+
+.tiptap {
+  :first-child {
+    margin-top: 0;
+  }
+  .mention {
+    background-color: var(--purple-light-dark);
+    border-radius: 0.4rem;
+    box-decoration-break: clone;
+    color: var(--white);
+    // font-weight: 600;
+    padding: 0.1rem 0.3rem;
+  }
+}
+
+.mention {
+  background-color: var(--purple-light-dark);
+  border-radius: 0.4rem;
+  box-decoration-break: clone;
+  color: var(--white);
+  // font-weight: 600;
+  padding: 0.1rem 0.3rem;
+}

+ 8 - 0
agenthub/public/MentionListV2Light.scss

@@ -42,4 +42,12 @@
       color: var(--purple);
       padding: 0.1rem 0.3rem;
     }
+  }
+
+  .mention {
+    background-color: var(--purple-light);
+    border-radius: 0.4rem;
+    box-decoration-break: clone;
+    color: var(--purple);
+    padding: 0.1rem 0.3rem;
   }