BR 6.3 — Admin BFF
Добавить proxy-роут для AI-агента (SSE-стрим pass-through).
Файлы для создания
bff/src/routes/agent.ts — новый файл:
import type { FastifyInstance } from 'fastify';
const AGENT_URL = process.env.AGENT_SERVICE_URL ?? 'http://openclaw-agent:3031';
export async function agentRoutes(app: FastifyInstance) {
// SSE pass-through
app.post('/api/v1/admin/agent/chat', async (req, reply) => {
const upstream = await fetch(`${AGENT_URL}/api/v1/admin/agent/chat`, {
method: 'POST',
headers: {
'Authorization': req.headers.authorization ?? '',
'Content-Type': 'application/json',
'Accept': 'text/event-stream',
},
body: JSON.stringify(req.body),
});
if (!upstream.ok || !upstream.body) {
reply.code(upstream.status);
return upstream.json().catch(() => ({ error: { code: 'AGENT_ERROR' } }));
}
reply.raw.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache, no-transform',
'Connection': 'keep-alive',
'X-Accel-Buffering': 'no', // nginx — не буферизуй
});
const reader = upstream.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
reply.raw.write(value);
}
reply.raw.end();
});
// CRUD пробрасываем как обычные REST
['GET', 'DELETE', 'POST'].forEach(method => {
app[method.toLowerCase() as 'get'](`/api/v1/admin/agent/conversations*`, async (req, reply) => {
const url = `${AGENT_URL}${req.url}`;
const r = await fetch(url, {
method,
headers: { 'Authorization': req.headers.authorization ?? '' },
body: method === 'GET' ? undefined : JSON.stringify(req.body),
});
reply.code(r.status);
return r.json().catch(() => ({}));
});
});
}Регистрация
bff/src/server.ts:
import { agentRoutes } from './routes/agent.js';
// ...
app.register(agentRoutes);Env
envs/admin-bff.env:
AGENT_SERVICE_URL=http://openclaw-agent:3031
Nginx
erp-infrastructure/nginx/conf.d/erp.conf — admin-bff проксируется по /api/v1/admin/*. Изменений не требуется, но проверить что для /api/v1/admin/agent/chat отключено буфферирование:
location /api/v1/admin/agent/chat {
proxy_pass http://admin-bff:3020;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 600s;
}(Если общее правило location /api/v1/admin/ уже отключает буферизацию для всего admin-API — отдельное правило не нужно.)
Тесты
- E2E через тестовый клиент: SSE-стрим от admin-bff пробрасывается без задержек > 100ms
Готовность
- Файл
bff/src/routes/agent.tsсоздан - Зарегистрирован в
server.ts - Env-переменная добавлена в
envs/admin-bff.envи в.env.example - Nginx проверен/обновлён
- Локально
curl --no-buffer -X POST .../api/v1/admin/agent/chatстримит данные с задержкой ≤ 100ms