| const express = require('express'); |
| const http = require('http'); |
| const { Server } = require('socket.io'); |
| const cors = require('cors'); |
| const fs = require('fs').promises; |
| const path = require('path'); |
| const { exec } = require('child_process'); |
|
|
| const app = express(); |
| app.use(cors()); |
| app.use(express.json()); |
|
|
| |
| const WORKSPACE_DIR = path.join(__dirname, 'workspace'); |
| async function ensureWorkspace() { |
| try { |
| await fs.access(WORKSPACE_DIR); |
| } catch { |
| await fs.mkdir(WORKSPACE_DIR, { recursive: true }); |
| |
| await fs.writeFile( |
| path.join(WORKSPACE_DIR, 'index.html'), |
| `<!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>Demo App</title> |
| </head> |
| <body> |
| <h1>Hello AgentIDE!</h1> |
| <p>This is a sample project.</p> |
| </body> |
| </html>` |
| ); |
| await fs.writeFile( |
| path.join(WORKSPACE_DIR, 'app.js'), |
| `// Main application file |
| console.log('AgentIDE demo app starting...'); |
| |
| function greet(name) { |
| return \`Hello, \${name}!\`; |
| } |
| |
| const result = greet('World'); |
| console.log(result);` |
| ); |
| await fs.writeFile( |
| path.join(WORKSPACE_DIR, 'styles.css'), |
| `/* Demo styles */ |
| body { |
| font-family: Arial, sans-serif; |
| margin: 0; |
| padding: 20px; |
| background: #1e1e1e; |
| color: #d4d4d4; |
| } |
| |
| h1 { |
| color: #4fc1ff; |
| }` |
| ); |
| await fs.writeFile( |
| path.join(WORKSPACE_DIR, 'package.json'), |
| JSON.stringify({ |
| name: 'demo-project', |
| version: '1.0.0', |
| scripts: { |
| test: 'echo "Tests passed!" && exit 0' |
| } |
| }, null, 2) |
| ); |
| await fs.mkdir(path.join(WORKSPACE_DIR, 'src'), { recursive: true }); |
| await fs.writeFile( |
| path.join(WORKSPACE_DIR, 'src', 'utils.js'), |
| `// Utility functions |
| export function add(a, b) { |
| return a + b; |
| } |
| |
| export function multiply(a, b) { |
| return a * b; |
| }` |
| ); |
| } |
| } |
|
|
| |
| app.get('/api/files', async (req, res) => { |
| try { |
| const files = await readDirectory(WORKSPACE_DIR); |
| res.json(files); |
| } catch (error) { |
| res.status(500).json({ error: error.message }); |
| } |
| }); |
|
|
| app.get('/api/files/*', async (req, res) => { |
| try { |
| const filePath = path.join(WORKSPACE_DIR, req.params[0]); |
| const content = await fs.readFile(filePath, 'utf-8'); |
| res.json({ content }); |
| } catch (error) { |
| res.status(500).json({ error: error.message }); |
| } |
| }); |
|
|
| app.post('/api/files/*', async (req, res) => { |
| try { |
| const filePath = path.join(WORKSPACE_DIR, req.params[0]); |
| const dir = path.dirname(filePath); |
| await fs.mkdir(dir, { recursive: true }); |
| await fs.writeFile(filePath, req.body.content, 'utf-8'); |
| res.json({ success: true }); |
| } catch (error) { |
| res.status(500).json({ error: error.message }); |
| } |
| }); |
|
|
| app.delete('/api/files/*', async (req, res) => { |
| try { |
| const filePath = path.join(WORKSPACE_DIR, req.params[0]); |
| await fs.unlink(filePath); |
| res.json({ success: true }); |
| } catch (error) { |
| res.status(500).json({ error: error.message }); |
| } |
| }); |
|
|
| app.post('/api/files/create-folder/*', async (req, res) => { |
| try { |
| const folderPath = path.join(WORKSPACE_DIR, req.params[0]); |
| await fs.mkdir(folderPath, { recursive: true }); |
| res.json({ success: true }); |
| } catch (error) { |
| res.status(500).json({ error: error.message }); |
| } |
| }); |
|
|
| app.post('/api/files/rename', async (req, res) => { |
| try { |
| const { oldPath, newPath } = req.body; |
| const fullOldPath = path.join(WORKSPACE_DIR, oldPath); |
| const fullNewPath = path.join(WORKSPACE_DIR, newPath); |
| await fs.rename(fullOldPath, fullNewPath); |
| res.json({ success: true }); |
| } catch (error) { |
| res.status(500).json({ error: error.message }); |
| } |
| }); |
|
|
| |
| app.post('/api/ai/chat', async (req, res) => { |
| const { message, context } = req.body; |
| |
| |
| const responses = { |
| 'summarize': { |
| type: 'summary', |
| content: `# Project Summary |
| |
| This is a demo project with the following structure: |
| - **index.html**: Main HTML entry point |
| - **app.js**: JavaScript application logic |
| - **styles.css**: Styling definitions |
| - **package.json**: Project configuration |
| - **src/utils.js**: Utility functions |
| |
| The project appears to be a simple web application demonstrating basic functionality.` |
| }, |
| 'explain': { |
| type: 'explanation', |
| content: `The code you've selected is a simple greeting function that takes a name parameter and returns a formatted string. It uses template literals for string interpolation.` |
| }, |
| 'default': { |
| type: 'response', |
| content: `I've analyzed your request. Based on the project structure, I can help you with: |
| |
| 1. Creating new files and folders |
| 2. Refactoring existing code |
| 3. Generating unit tests |
| 4. Explaining code snippets |
| 5. Running commands and tests |
| |
| What would you like me to do?` |
| } |
| }; |
|
|
| |
| let response = responses.default; |
| if (message.toLowerCase().includes('summarize') || message.toLowerCase().includes('structure')) { |
| response = responses.summarize; |
| } else if (message.toLowerCase().includes('explain')) { |
| response = responses.explain; |
| } |
|
|
| res.json(response); |
| }); |
|
|
| |
| app.post('/api/execute', (req, res) => { |
| const { command } = req.body; |
| |
| exec(command, { cwd: WORKSPACE_DIR }, (error, stdout, stderr) => { |
| res.json({ |
| success: !error, |
| output: stdout || stderr, |
| error: error ? error.message : null |
| }); |
| }); |
| }); |
|
|
| |
| async function readDirectory(dir, basePath = '') { |
| const entries = await fs.readdir(dir, { withFileTypes: true }); |
| const result = []; |
|
|
| for (const entry of entries) { |
| const fullPath = path.join(dir, entry.name); |
| const relativePath = path.join(basePath, entry.name); |
|
|
| if (entry.isDirectory()) { |
| result.push({ |
| name: entry.name, |
| path: relativePath, |
| type: 'folder', |
| children: await readDirectory(fullPath, relativePath) |
| }); |
| } else { |
| const stats = await fs.stat(fullPath); |
| result.push({ |
| name: entry.name, |
| path: relativePath, |
| type: 'file', |
| size: stats.size, |
| extension: path.extname(entry.name).slice(1) |
| }); |
| } |
| } |
|
|
| return result; |
| } |
|
|
| |
| const server = http.createServer(app); |
| const io = new Server(server, { |
| cors: { |
| origin: '*', |
| methods: ['GET', 'POST'] |
| } |
| }); |
|
|
| io.on('connection', (socket) => { |
| console.log('Client connected'); |
|
|
| socket.on('terminal-input', (data) => { |
| |
| exec(data.command, { cwd: WORKSPACE_DIR }, (error, stdout, stderr) => { |
| socket.emit('terminal-output', { |
| output: stdout || stderr || `Command: ${data.command}`, |
| error: !!error |
| }); |
| }); |
| }); |
|
|
| socket.on('file-change', (data) => { |
| socket.broadcast.emit('file-updated', data); |
| }); |
|
|
| socket.on('disconnect', () => { |
| console.log('Client disconnected'); |
| }); |
| }); |
|
|
| |
| ensureWorkspace().then(() => { |
| const PORT = process.env.PORT || 3001; |
| server.listen(PORT, () => { |
| console.log(`AgentIDE server running on http://localhost:${PORT}`); |
| console.log(`Workspace: ${WORKSPACE_DIR}`); |
| }); |
| }); |
|
|
| module.exports = app; |