Spaces:
Build error
Build error
File size: 6,943 Bytes
d83e271 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# Package Detection and Installation Guide
This document explains how to use the XML-based package detection and installation mechanism in the E2B sandbox environment.
## Overview
The E2B sandbox can automatically detect and install packages from XML tags in AI-generated code responses. This mechanism works alongside the existing file detection system.
## XML Tag Formats
### Individual Package Tags
Use `<package>` tags for individual packages:
```xml
<package>react-router-dom</package>
<package>axios</package>
<package>@heroicons/react</package>
```
### Multiple Packages Tag
Use `<packages>` tag for multiple packages (comma or newline separated):
```xml
<packages>
react-router-dom
axios
@heroicons/react
framer-motion
</packages>
```
Or comma-separated:
```xml
<packages>react-router-dom, axios, @heroicons/react, framer-motion</packages>
```
### Command Execution
Use `<command>` tags to execute shell commands in the sandbox:
```xml
<command>npm run build</command>
<command>npm run test</command>
```
## Complete Example
Here's a complete example of an AI response with files, packages, and commands:
```xml
<explanation>
Creating a React application with routing and API integration.
</explanation>
<packages>
react-router-dom
axios
@heroicons/react
</packages>
<file path="src/App.jsx">
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { HomeIcon } from '@heroicons/react/24/solid';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
function App() {
return (
<Router>
<div className="min-h-screen bg-gray-100">
<nav className="bg-white shadow-lg p-4">
<HomeIcon className="h-6 w-6" />
</nav>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
</Routes>
</div>
</Router>
);
}
export default App;
</file>
<file path="src/pages/HomePage.jsx">
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function HomePage() {
const [data, setData] = useState(null);
useEffect(() => {
axios.get('/api/data')
.then(response => setData(response.data))
.catch(error => console.error('Error fetching data:', error));
}, []);
return (
<div className="container mx-auto p-8">
<h1 className="text-3xl font-bold">Home Page</h1>
{data && <pre>{JSON.stringify(data, null, 2)}</pre>}
</div>
);
}
export default HomePage;
</file>
<file path="src/pages/AboutPage.jsx">
import React from 'react';
function AboutPage() {
return (
<div className="container mx-auto p-8">
<h1 className="text-3xl font-bold">About Page</h1>
<p>This is the about page of our application.</p>
</div>
);
}
export default AboutPage;
</file>
<command>npm run dev</command>
</xml>
```
## How It Works
1. **Parsing**: The `parseAIResponse` function in `/app/api/apply-ai-code/route.ts` extracts:
- Files from `<file>` tags
- Packages from `<package>` and `<packages>` tags
- Commands from `<command>` tags
2. **Package Installation**:
- Packages are automatically installed using npm
- Both scoped packages (e.g., `@heroicons/react`) and regular packages are supported
- The system checks if packages are already installed to avoid redundant installations
3. **File Creation**: Files are created in the sandbox after packages are installed
4. **Command Execution**: Commands are executed in the sandbox environment
## API Endpoints
### `/api/apply-ai-code`
Main endpoint that processes AI responses containing XML tags.
**Request body:**
```json
{
"response": "<AI response with XML tags>",
"isEdit": false,
"packages": [] // Optional array of packages
}
```
### `/api/detect-and-install-packages`
Detects packages from import statements in code files.
**Request body:**
```json
{
"files": {
"src/App.jsx": "import React from 'react'...",
"src/utils.js": "import axios from 'axios'..."
}
}
```
### `/api/install-packages`
Directly installs packages in the sandbox.
**Request body:**
```json
{
"packages": ["react-router-dom", "axios", "@heroicons/react"]
}
```
## Features
- **Automatic Package Detection**: Extracts packages from import statements
- **Duplicate Prevention**: Avoids installing already-installed packages
- **Scoped Package Support**: Handles packages like `@heroicons/react`
- **Built-in Module Filtering**: Skips Node.js built-in modules
- **Real-time Feedback**: Provides installation progress updates
- **Error Handling**: Reports failed installations
## Best Practices
1. **Specify packages explicitly** using XML tags when possible
2. **Group related packages** in a single `<packages>` tag
3. **Order matters**: Packages are installed before files are created
4. **Use commands** for post-installation tasks like building or testing
## Integration with E2B Sandbox
The package detection mechanism integrates seamlessly with the E2B sandbox:
1. Packages are installed in `/home/user/app/node_modules`
2. The Vite dev server is automatically restarted after package installation
3. All npm operations run within the sandbox environment
4. Package.json is automatically updated with new dependencies
## E2B Command Execution Methods
### Method 1: Using runCode() with Python subprocess
```javascript
// Current implementation pattern
await global.activeSandbox.runCode(`
import subprocess
import os
os.chdir('/home/user/app')
result = subprocess.run(['npm', 'install', 'axios'], capture_output=True, text=True)
print(result.stdout)
`);
```
### Method 2: Using commands.run() directly (Recommended)
```javascript
// Direct command execution - cleaner approach
const result = await global.activeSandbox.commands.run('npm install axios', {
cwd: '/home/user/app',
timeout: 60000
});
console.log(result.stdout);
```
### Command Execution Options
When using `sandbox.commands.run()`, you can specify:
- `cmd`: Command string to execute
- `background`: Run in background (true) or wait for completion (false)
- `envs`: Environment variables as key-value pairs
- `user`: User to run command as (default: "user")
- `cwd`: Working directory
- `on_stdout`: Callback for stdout output
- `on_stderr`: Callback for stderr output
- `timeout`: Command timeout in seconds (default: 60)
### Example: Installing packages with commands.run()
```javascript
// Install multiple packages
const packages = ['react-router-dom', 'axios', '@heroicons/react'];
const result = await global.activeSandbox.commands.run(
`npm install ${packages.join(' ')}`,
{
cwd: '/home/user/app',
timeout: 120,
on_stdout: (data) => console.log('npm:', data),
on_stderr: (data) => console.error('npm error:', data)
}
);
if (result.exitCode === 0) {
console.log('Packages installed successfully');
} else {
console.error('Installation failed:', result.stderr);
} |