#!/usr/bin/env node import http from 'node:http' import fs from 'node:fs' import path from 'node:path' import crypto from 'node:crypto' const agentDir = process.env.PI_CODING_AGENT_DIR const sessionDir = process.env.PI_CODING_AGENT_SESSION_DIR const markerDir = process.env.PIAGENTUI_E2E_MARKER_DIR if (!agentDir || !sessionDir) { console.error('PI_CODING_AGENT_DIR and PI_CODING_AGENT_SESSION_DIR are required') process.exit(2) } fs.mkdirSync(agentDir, { recursive: true }) fs.mkdirSync(sessionDir, { recursive: true }) if (markerDir) fs.mkdirSync(markerDir, { recursive: true }) const token = `e2e-${crypto.randomUUID()}` let apiKeyConfigured = false let lastApiKeyLength const requests = [] const providers = () => [ { id: 'opencode', name: 'OpenCode Zen', models: [ { id: 'deepseek-v4-flash', name: 'DeepSeek V4 Flash', providerId: 'opencode', providerName: 'OpenCode Zen', }, ], auth: { method: 'apikey', authorization: { configured: apiKeyConfigured } }, }, { id: 'anthropic', name: 'Anthropic', models: [{ id: 'claude-sonnet-4', name: 'Claude Sonnet 4', providerId: 'anthropic', providerName: 'Anthropic' }], auth: { method: 'oauth', authorization: { configured: false } }, }, { id: 'google', name: 'Google', models: [{ id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash', providerId: 'google', providerName: 'Google' }], auth: { method: 'apikey', authorization: { configured: false } }, }, ] function writeMarker(extra = {}) { if (!markerDir) return fs.writeFileSync( path.join(markerDir, 'fake-pi-state.json'), JSON.stringify( { pid: process.pid, agentDir, sessionDir, startupArgs: process.argv.slice(2), apiKeyConfigured, lastApiKeyLength, requests, ...extra, }, null, 2, ), 'utf8', ) } function sendJson(res, status, body) { res.writeHead(status, { 'Content-Type': 'application/json' }) res.end(JSON.stringify(body)) } async function readBody(req) { const chunks = [] for await (const chunk of req) chunks.push(chunk) const raw = Buffer.concat(chunks).toString('utf8') if (!raw) return {} return JSON.parse(raw) } const server = http.createServer(async (req, res) => { const url = new URL(req.url ?? '/', 'http://127.0.0.1') requests.push({ method: req.method, path: url.pathname }) writeMarker() if (req.method === 'GET' && url.pathname === '/global/health') { return sendJson(res, 200, { ok: true, mode: 'rpc' }) } if (req.method === 'GET' && url.pathname === '/api/health') { return sendJson(res, 200, { status: 'ok', version: 'e2e' }) } if (req.method === 'GET' && url.pathname === '/api/providers') { return sendJson(res, 200, { providers: providers(), default: {} }) } if (req.method === 'POST' && url.pathname === '/api/providers/opencode/api-key') { const body = await readBody(req) apiKeyConfigured = Boolean(body.apiKey) lastApiKeyLength = typeof body.apiKey === 'string' ? body.apiKey.length : 0 writeMarker() return sendJson(res, 200, { ok: true }) } if (req.method === 'POST' && url.pathname === '/api/providers/opencode/logout') { apiKeyConfigured = false writeMarker() return sendJson(res, 200, { ok: true }) } if (req.method === 'GET' && url.pathname === '/api/models') { return sendJson(res, 200, { models: providers().flatMap(provider => provider.models) }) } if (req.method === 'GET' && url.pathname === '/api/sessions') { return sendJson(res, 200, { sessions: [] }) } if (req.method === 'GET' && url.pathname === '/api/runtime/capabilities') { return sendJson(res, 200, { commands: true, extensions: true, providerAuth: true }) } if (req.method === 'GET' && url.pathname === '/api/commands') { return sendJson(res, 200, { commands: [] }) } if (req.method === 'GET' && url.pathname === '/api/agents') { return sendJson(res, 200, { agents: [] }) } if (req.method === 'GET' && url.pathname === '/api/skills') { return sendJson(res, 200, { skills: {} }) } if (req.method === 'GET' && url.pathname === '/api/mcp/status') { return sendJson(res, 200, { servers: {}, tools: [] }) } if (req.method === 'GET' && url.pathname === '/api/network/access') { return sendJson(res, 200, { lanAccessEnabled: false, urls: [] }) } if (req.method === 'GET' && url.pathname.startsWith('/api/settings/')) { return sendJson(res, 200, {}) } sendJson(res, 404, { error: `Unhandled fake Pi route: ${req.method} ${url.pathname}` }) }) server.listen(0, '127.0.0.1', () => { const address = server.address() if (!address || typeof address === 'string') throw new Error('No TCP address') const discovery = { port: address.port, token, pid: process.pid, startedAt: new Date().toISOString() } fs.writeFileSync(path.join(agentDir, 'piagentui-port.json'), JSON.stringify(discovery, null, 2), 'utf8') writeMarker({ port: address.port }) }) process.on('SIGTERM', () => server.close(() => process.exit(0))) process.on('SIGINT', () => server.close(() => process.exit(0)))