- Create a nodejs server that exposes an endpoint
/prompt where user can send their prompt and get back an e2b preview url
import express from "express";
const app = express();
app.post("/prompt", (req, res) => {
const { prompt } = req.body;
// create sandbox for user
// forward enriched prompt to llm
// Define toolcalls that write to the sandbox.
});
app.listen(3000, () => {
console.log("Server is running on port 3000");
});
- Define tools in
tools/index.ts
import { z } from "zod";
export const createFile = {
description: 'Create a file at a certain directory',
parameters: z.object({
location: z
.string()
.describe('Relative path to the file')
}),
execute: async ({ location }: { location: string }) => {
return `File created`;
},
};
export const updateFile = {
description: 'Update a file at a certain directory',
parameters: z.object({
location: z.string().describe('Relative path to the file'),
content: z.string().describe('Content of the file'),
}),
execute: async ({ location, content }: { location: string, content: string }) => {
return `File updated`;
},
};
export const deleteFile = {
description: 'Delete a file at a certain directory',
parameters: z.object({
location: z.string().describe('Relative path to the file'),
}),
execute: async ({ location }: { location: string }) => {
return `File deleted`;
},
};
export const readFile = {
description: 'Read a file at a certain directory',
parameters: z.object({
location: z.string().describe('Relative path to the file'),
}),
execute: async ({ location }: { location: string }) => {
return `File Contents`;
},
};
- Write the system prompt, give access to the tools, test the LLM integration.
export const appTsx = `
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<>
<div>
<a href="<https://vite.dev>" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="<https://react.dev>" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
}
export default App
`
export const initialFileStructure = `
- /home/user/index.html
- /home/user/package.json
- /home/user/README.md
- /home/user/src/
- /home/user/src/App.tsx
- /home/user/src/App.css
- /home/user/src/index.css
- /home/user/src/main.tsx
App.tsx looks like this:
${appTsx}
`;
export const SYSTEM_PROMPT = `
You are an expert coding agent. Your job is to write code in a sandbox environment.
You have access to the following tools:
- createFile
- updateFile
- deleteFile
- readFile
You will be given a prompt and you will need to write code to implement the prompt.
Make sure the website is pretty.
This is what the initial file structure looks like:
${initialFileStructure}
`
import express from "express";
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
import { streamText } from 'ai';
import { SYSTEM_PROMPT } from "./prompt";
import { createFile, updateFile, deleteFile, readFile } from "./tools";
import { z } from "zod";
const app = express();
app.use(express.json());
app.post("/prompt", (req, res) => {
const { prompt } = req.body;
// TODO: create sandbox for user
const openrouter = createOpenRouter({
apiKey: process.env.OPENROUTER_API_KEY,
});
const response = streamText({
model: openrouter("gpt-4o-mini"),
tools: {
createFile: createFile,
updateFile: updateFile,
deleteFile: deleteFile,
readFile: readFile
},
messages: [
{
role: "system",
content: SYSTEM_PROMPT
},
{
role: "user",
content: prompt
}
]
});
response.pipeTextStreamToResponse(res);
});
app.listen(3000, () => {
console.log("Server is running on port 3000");
});