Skip to content

Commit

Permalink
Fixing logic in chat interface and terminal
Browse files Browse the repository at this point in the history
  • Loading branch information
akhatua2 committed Nov 22, 2024
1 parent 21b3322 commit 36646a8
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 67 deletions.
24 changes: 18 additions & 6 deletions examples/experimental/nodes/frontend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,24 @@ io.on('connection', (socket) => {
console.log('A user connected');

socket.on('terminal_command', async (command) => {
console.log(`Received command: ${command}`);
// try {
// await redisClient.publish('TerminalChannel', command); // Publish to a Redis channel
// } catch (err) {
// console.error('Error publishing to Redis:', err);
// }
// console.log(`Received command: ${command}`);
// Create the message envelope that matches the Python Message[AgentAction] structure
const messageEnvelope = {
data: {
agent_name: "Terminal",
action_type: "run",
argument: command,
path: "",
data_type: "agent_action" // This needs to be inside the data object
}
};

try {
// Publish the JSON-serialized message to the Agent:Runtime channel
await redisClient.publish('Agent:Runtime', JSON.stringify(messageEnvelope));
} catch (err) {
console.error('Error publishing to Redis:', err);
}
});

socket.on('disconnect', () => {
Expand Down
121 changes: 80 additions & 41 deletions examples/experimental/nodes/frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,27 @@ const App: React.FC = () => {

useEffect(() => {
const handleNewMessage = (data: any) => {
const messageData = JSON.parse(data.message);
if (messageData.data.data_type === "agent_action") {
handleAgentAction(messageData);
} else if (messageData.data.data_type === "text" && messageData.data.text.includes("CmdOutputObservation")) {
const parts = messageData.data.text.split("**CmdOutputObservation (source=None, exit code=0)**");
if (parts.length > 1) {
const outputText = parts[1].trim();
setTerminalMessages((prev) => [...prev, outputText]);
try {
const messageData = JSON.parse(data.message);

// Check if it's an agent action
if (messageData.data?.data_type === "agent_action") {
handleAgentAction(messageData);
}
// Check if it's a command output
else if (messageData.data?.data_type === "text" &&
messageData.data.text.includes("CmdOutputObservation")) {
const parts = messageData.data.text.split("**CmdOutputObservation (source=None, exit code=0)**");
if (parts.length > 1) {
const outputText = parts[1].trim();
setTerminalMessages(prev => [...prev, outputText]);
}
}
// Log the message for debugging
console.log('Parsed message:', messageData);

} catch (error) {
console.error('Error parsing message:', error);
}
};

Expand All @@ -67,45 +79,63 @@ const App: React.FC = () => {
const actionType = messageData.data.action_type;
const agentName = messageData.data.agent_name;

if (actionType === "speak") {
const newMessage = {
text: `${agentName}: ${messageData.data.argument}`,
type: 'message' as const
};
setMessages(prev => [...prev, newMessage]);
} else if (actionType === "write") {
const filePath = messageData.data.path;
const fileContent = messageData.data.argument;
setFiles(prevFiles => ({ ...prevFiles, [filePath]: fileContent }));
setActiveTab('editor');
const statusMessage = {
text: `${agentName} is writing code...`,
type: 'status' as const
};
setMessages(prev => [...prev, statusMessage]);
} else if (actionType === "run") {
setTerminalMessages((prev) => [...prev, `$ ${messageData.data.argument}`]);
const statusMessage = {
text: `${agentName} is executing a command...`,
type: 'status' as const
};
setMessages(prev => [...prev, statusMessage]);
} else if (actionType === "browse") {
const url = messageData.data.argument;
setBrowserUrl(url);
setActiveTab('browser');
const statusMessage = {
text: `${agentName} is browsing ${url}`,
type: 'status' as const
};
setMessages(prev => [...prev, statusMessage]);
// Always log the action for debugging
console.log('Processing agent action:', actionType, 'from', agentName);

switch (actionType) {
case "speak":
const newMessage = {
text: `${agentName}: ${messageData.data.argument}`,
type: 'message' as const
};
setMessages(prev => [...prev, newMessage]);
break;

case "write":
const filePath = messageData.data.path;
const fileContent = messageData.data.argument;
setFiles(prev => ({ ...prev, [filePath]: fileContent }));
setActiveTab('editor');
setMessages(prev => [...prev, {
text: `${agentName} is writing code...`,
type: 'status' as const
}]);
break;

case "run":
setTerminalMessages(prev => [...prev, `$ ${messageData.data.argument}`]);
setMessages(prev => [...prev, {
text: `${agentName} is executing a command...`,
type: 'status' as const
}]);
break;

case "browse":
const url = messageData.data.argument;
setBrowserUrl(url);
setActiveTab('browser');
setMessages(prev => [...prev, {
text: `${agentName} is browsing ${url}`,
type: 'status' as const
}]);
break;

default:
console.log('Unknown action type:', actionType);
}
};

const handleSidebarSelect = (option: PanelOption) => {
setActivePanel(option);
};

socket.on('chat_message', (message: string) => {
setMessages(prev => [...prev, {
text: message,
type: 'message' as const
}]);
});

return (
<div className="App">
<Sidebar onSelect={handleSidebarSelect} />
Expand Down Expand Up @@ -152,7 +182,16 @@ const App: React.FC = () => {
</div>
</div>
<div id="chat-container">
<ChatInterface messages={messages} socket={socket}/>
<ChatInterface
messages={messages}
socket={socket}
onSendMessage={(text: string) => {
setMessages(prev => [...prev, {
text: `User: ${text}`,
type: 'message' as const
}]);
}}
/>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
font-size: 0.875rem;
color: #808080;
margin-bottom: 4px;
padding-left: 10px;
}

.message-bubble {
Expand Down Expand Up @@ -109,6 +110,7 @@
text-align: right;
width: 100%;
color: #808080;
padding-right: 10px;
}

.message[data-sender="Jane"] .message-content-wrapper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,18 @@ interface ChatInterfaceProps {
type: 'message' | 'status';
}>;
socket: Socket;
onSendMessage: (text: string) => void;
}

export const ChatInterface: React.FC<ChatInterfaceProps> = ({ messages: initialMessages , socket}) => {
const [messages, setMessages] = useState(initialMessages);
export const ChatInterface: React.FC<ChatInterfaceProps> = ({
messages,
socket,
onSendMessage
}) => {
const [input, setInput] = useState('');
const messagesEndRef = React.useRef<HTMLDivElement>(null);

console.log("ChatInterface received messages:", messages);

const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
Expand All @@ -43,14 +49,10 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({ messages: initialM
scrollToBottom();
}, [messages]);


const handleSend = () => {
if (input.trim()) {
setMessages([...messages, {
text: `User: ${input}`, // Prefix with "User:"
type: 'message'
}]);
socket.emit('chat_message', `User: ${input}`); // Emit the command to the server
socket.emit('chat_message', input.trim());
onSendMessage(input.trim());
setInput('');
}
};
Expand All @@ -64,6 +66,13 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({ messages: initialM
};
}
const colonIndex = message.text.indexOf(':');
if (colonIndex === -1) {
return {
agentName: 'System',
text: message.text,
type: 'message'
};
}
const agentName = message.text.slice(0, colonIndex);
const text = message.text.slice(colonIndex + 1).trim();
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ const processTerminalLine = (line: string): JSX.Element => {
if (line.startsWith('Requirement already satisfied:')) {
return <div style={{ color: '#00ff00' }}>{stripAnsiCodes(line)}</div>;
}
if (line.startsWith('$')) {
return <div style={{ color: '#00ff00' }}>{stripAnsiCodes(line)}</div>;
}
if (line.includes('notice')) {
return <div style={{ color: '#808080' }}>{stripAnsiCodes(line)}</div>;
}
Expand All @@ -40,28 +37,29 @@ export const Terminal: React.FC<TerminalProps> = ({ externalMessages, socket })

useEffect(() => {
if (externalMessages.length > 0) {
setHistory((prevHistory) => [...prevHistory, ...externalMessages]);
// Append the latest message to history
setHistory((prevHistory) => [
...prevHistory,
externalMessages[externalMessages.length - 1],
]);
}
}, [externalMessages]);

const handleCommand = (command: string) => {
setHistory([...history, `$ ${command}`, '']);
setInput('');
console.log('Command: ' + command);
socket.emit('terminal_command', command); // Emit the command to the server
// Optionally, you can add the command to history if desired
// setHistory((prevHistory) => [...prevHistory, `$ ${command}`]);
};

return (
<div className="terminal-container">
<div id="terminal-header">
<FaTerminal size={12} style={{ marginRight: '8px', verticalAlign: 'middle' }} />
<FaTerminal size={12} style={{ marginRight: '8px', verticalAlign: 'middle' }} />
<span className="terminal-title">Terminal</span>
</div>
<div className="terminal-body">
<div
ref={historyRef}
className="terminal-history"
>
<div ref={historyRef} className="terminal-history">
{history.map((line, index) => (
<div key={index} className="terminal-line">
{processTerminalLine(line)}
Expand All @@ -82,4 +80,4 @@ export const Terminal: React.FC<TerminalProps> = ({ externalMessages, socket })
</div>
</div>
);
};
};

0 comments on commit 36646a8

Please sign in to comment.