Skip to content

Commit

Permalink
Merge pull request #19 from autonomys/agent-frontend
Browse files Browse the repository at this point in the history
Agent frontend
  • Loading branch information
jfrank-summit authored Nov 1, 2024
2 parents 612d892 + 1b75631 commit 7eb18eb
Show file tree
Hide file tree
Showing 20 changed files with 2,860 additions and 214 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ node_modules/
*.sqlite
*.sqlite-journal

resources/
resources/
threads.json
6 changes: 3 additions & 3 deletions auto-chain-agent/agents/export_threads.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

sqlite3 thread-storage.sqlite "SELECT json_group_array(json_object(
'thread_id', thread_id,
'state', state,
'last_output', last_output,
'messages', messages,
'tool_calls', tool_calls,
'created_at', created_at,
'updated_at', updated_at
)) FROM threads;" | jq '.' > threads.json
)) FROM threads;" | jq '.' > threads.json
4 changes: 3 additions & 1 deletion auto-chain-agent/agents/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@langchain/langgraph": "0.2.8",
"@langchain/openai": "0.3.1",
"axios": "^1.7.7",
"cors": "^2.8.5",
"dotenv": "^16.4.1",
"express": "5.0.0",
"sqlite": "^5.1.1",
Expand All @@ -27,10 +28,11 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "5.0.0",
"@types/node": "22.6.1",
"nodemon": "^3.0.1",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
}
}
2 changes: 2 additions & 0 deletions auto-chain-agent/agents/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import express from 'express';
import { chainRouter } from './routes/chainAgentRoutes';
import logger from './logger';
import { config } from './config';
import cors from 'cors';

const app = express();
const port = config.port || 3000;

app.use(express.json());
app.use(cors());

// Routes
app.use('/chainagent', chainRouter);
Expand Down
24 changes: 0 additions & 24 deletions auto-chain-agent/agents/src/types.ts

This file was deleted.

157 changes: 1 addition & 156 deletions auto-chain-agent/agents/threads.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions auto-chain-agent/frontend/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_API_URL=http://localhost:3000
17 changes: 17 additions & 0 deletions auto-chain-agent/frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<title>Autonomys Network - Chain Agent</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>

</html>
37 changes: 37 additions & 0 deletions auto-chain-agent/frontend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "@auto-chain/frontend",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@chakra-ui/icons": "^2.1.1",
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"framer-motion": "11.11.11",
"axios": "^1.6.7",
"date-fns": "4.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^9.0.1"
},
"devDependencies": {
"@types/node": "22.8.6",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19",
"@typescript-eslint/eslint-plugin": "8.12.2",
"@typescript-eslint/parser": "8.12.2",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "9.14.0",
"eslint-plugin-react-hooks": "5.0.0",
"eslint-plugin-react-refresh": "^0.4.5",
"typescript": "^5.2.2",
"vite": "^5.1.0"
}
}
Binary file added auto-chain-agent/frontend/public/favicon.ico
Binary file not shown.
93 changes: 93 additions & 0 deletions auto-chain-agent/frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { useState, useRef, useEffect } from 'react';
import { Box, Container, Heading, VStack } from '@chakra-ui/react';
import ChatInput from './components/ChatInput';
import MessageList from './components/MessageList';
import { Message } from './types';
import { sendMessage } from './api';

function App() {
const [messages, setMessages] = useState<Message[]>([]);
const [loading, setLoading] = useState(false);
const [currentThreadId, setCurrentThreadId] = useState<string | null>(null);
const messagesEndRef = useRef<HTMLDivElement>(null);

const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
};

useEffect(() => {
scrollToBottom();
}, [messages]);

const handleSendMessage = async (content: string) => {
if (!content.trim()) return;

const userMessage: Message = {
role: 'user',
content,
timestamp: new Date(),
};
setMessages(prev => [...prev, userMessage]);
setLoading(true);

try {
const response = await sendMessage(content, currentThreadId);
setCurrentThreadId(response.threadId);

const assistantMessage: Message = {
role: 'assistant',
content: response.response,
timestamp: new Date(),
toolCalls: response.toolCalls
};

setMessages(prev => [...prev, assistantMessage]);
} catch (error) {
console.error('Error sending message:', error);
const errorMessage: Message = {
role: 'error',
content: 'Sorry, there was an error processing your request.',
timestamp: new Date(),
};
setMessages(prev => [...prev, errorMessage]);
} finally {
setLoading(false);
}
};

return (
<Box minH="100vh" bg="gray.50">
<Box bg="white" py={4} shadow="sm">
<Container maxW="container.xl">
<Heading size="lg" color="gray.700">Autonomys Network - Chain Agent</Heading>
</Container>
</Box>

<Container maxW="container.xl" py={8}>
<Box
bg="white"
borderRadius="lg"
shadow="base"
height="calc(100vh - 180px)"
overflow="hidden"
>
<VStack h="full" spacing={0}>
<Box flex="1" w="full" overflowY="auto" p={4}>
<MessageList messages={messages} />
<div ref={messagesEndRef} />
</Box>

<Box w="full" p={4} borderTop="1px" borderColor="gray.100">
<ChatInput
onSendMessage={handleSendMessage}
disabled={loading}
/>
</Box>
</VStack>
</Box>
</Container>
</Box>
);
}

export default App;
27 changes: 27 additions & 0 deletions auto-chain-agent/frontend/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/// <reference types="vite/client" />
import axios from 'axios';

const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000';

export const sendMessage = async (message: string, threadId?: string | null) => {
try {
const response = await axios.post(`${API_URL}/chainagent`, {
message,
threadId
});
return response.data;
} catch (error) {
console.error('API Error:', error);
throw error;
}
};

export const getThreadState = async (threadId: string) => {
try {
const response = await axios.get(`${API_URL}/chainagent/${threadId}/state`);
return response.data;
} catch (error) {
console.error('API Error:', error);
throw error;
}
};
67 changes: 67 additions & 0 deletions auto-chain-agent/frontend/src/components/ChatInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useState, KeyboardEvent } from 'react';
import {
Button,
Textarea,
HStack,
useColorModeValue
} from '@chakra-ui/react';

interface ChatInputProps {
onSendMessage: (message: string) => void;
disabled?: boolean;
}

function ChatInput({ onSendMessage, disabled }: ChatInputProps) {
const [message, setMessage] = useState('');

const handleSubmit = () => {
if (message.trim() && !disabled) {
onSendMessage(message);
setMessage('');
}
};

const handleKeyPress = (e: KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSubmit();
}
};

const buttonBg = useColorModeValue('blue.500', 'blue.300');
const buttonHoverBg = useColorModeValue('blue.600', 'blue.400');

return (
<HStack spacing={4} align="end">
<Textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Type your message..."
disabled={disabled}
resize="none"
rows={3}
focusBorderColor="blue.500"
/>
<Button
onClick={handleSubmit}
isDisabled={disabled || !message.trim()}
bg={buttonBg}
color="white"
px={8}
h={12}
_hover={{
bg: buttonHoverBg
}}
_disabled={{
bg: 'gray.300',
cursor: 'not-allowed'
}}
>
Send
</Button>
</HStack>
);
}

export default ChatInput;
Loading

0 comments on commit 7eb18eb

Please sign in to comment.