| 222 | } |
| 223 | |
| 224 | export function appGeneratorPlugin(options: AppGeneratorOptions): Plugin { |
| 225 | let viteServer: import('vite').ViteDevServer | null = null; |
| 226 | |
| 227 | return { |
| 228 | name: 'app-generator', |
| 229 | configureServer(server) { |
| 230 | viteServer = server; |
| 231 | server.middlewares.use('/api/generate-apps', async (req, res) => { |
| 232 | if (req.method !== 'POST') { |
| 233 | res.writeHead(405, { 'Content-Type': 'application/json' }); |
| 234 | res.end(JSON.stringify({ error: 'Method not allowed' })); |
| 235 | return; |
| 236 | } |
| 237 | |
| 238 | const chunks: Buffer[] = []; |
| 239 | req.on('data', (chunk: Buffer) => chunks.push(chunk)); |
| 240 | req.on('end', async () => { |
| 241 | let body: { apps: AppInput[]; concurrency?: number }; |
| 242 | try { |
| 243 | body = JSON.parse(Buffer.concat(chunks).toString()); |
| 244 | } catch { |
| 245 | res.writeHead(400, { 'Content-Type': 'application/json' }); |
| 246 | res.end(JSON.stringify({ error: 'Invalid JSON' })); |
| 247 | return; |
| 248 | } |
| 249 | |
| 250 | const { apps, concurrency = 3 } = body; |
| 251 | console.log( |
| 252 | `${LOG_PREFIX} Received request: ${apps?.length ?? 0} apps, concurrency=${concurrency}`, |
| 253 | ); |
| 254 | if (!Array.isArray(apps) || apps.length === 0) { |
| 255 | console.error(`${LOG_PREFIX} Empty or invalid apps array`); |
| 256 | res.writeHead(400, { 'Content-Type': 'application/json' }); |
| 257 | res.end(JSON.stringify({ error: 'apps array is required' })); |
| 258 | return; |
| 259 | } |
| 260 | console.log( |
| 261 | `${LOG_PREFIX} Apps to generate:`, |
| 262 | apps.map((a) => `${a.id}(${a.name})`).join(', '), |
| 263 | ); |
| 264 | |
| 265 | // SSE headers |
| 266 | res.writeHead(200, { |
| 267 | 'Content-Type': 'text/event-stream', |
| 268 | 'Cache-Control': 'no-cache', |
| 269 | Connection: 'keep-alive', |
| 270 | }); |
| 271 | |
| 272 | const sendEvent = (data: Record<string, unknown>) => { |
| 273 | res.write(`data: ${JSON.stringify(data)}\n\n`); |
| 274 | }; |
| 275 | |
| 276 | // Lazy-import the Agent SDK (ESM) |
| 277 | console.log(`${LOG_PREFIX} Loading Agent SDK...`); |
| 278 | let queryFn: (typeof import('@anthropic-ai/claude-agent-sdk'))['query']; |
| 279 | try { |
| 280 | const sdk = await import('@anthropic-ai/claude-agent-sdk'); |
| 281 | queryFn = sdk.query; |