feat(gateway): add web UI with dashboard and chat interface
Refactor GatewayServer to serve HTTP and WebSocket on a shared http.Server. Add static file serving with path traversal protection, a dark-themed dashboard (system health, sessions, tools) and a WebSocket chat interface with streaming tool events and markdown rendering.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
|
||||
import { WebSocket } from 'ws';
|
||||
import { resolve } from 'path';
|
||||
import { GatewayServer } from './server.js';
|
||||
import type { GatewayServerConfig } from './server.js';
|
||||
import type { GatewayResponse, GatewayError, GatewayEvent } from './protocol.js';
|
||||
@@ -87,6 +88,7 @@ describe('GatewayServer integration', () => {
|
||||
toolRegistry: mockToolRegistry as unknown as GatewayServerConfig['toolRegistry'],
|
||||
toolExecutor: mockToolExecutor as unknown as GatewayServerConfig['toolExecutor'],
|
||||
version: '0.1.0-test',
|
||||
uiDir: resolve(import.meta.dirname, 'ui'),
|
||||
});
|
||||
await server.start();
|
||||
});
|
||||
@@ -185,4 +187,30 @@ describe('GatewayServer integration', () => {
|
||||
expect(methods).toContain('tools.list');
|
||||
expect(methods).toContain('tools.invoke');
|
||||
});
|
||||
|
||||
// ── HTTP static file serving tests ────────────────────────────
|
||||
|
||||
it('serves index.html on HTTP GET /', async () => {
|
||||
const res = await fetch(`http://127.0.0.1:${TEST_PORT}/`);
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.headers.get('content-type')).toBe('text/html');
|
||||
const body = await res.text();
|
||||
expect(body).toContain('Flynn');
|
||||
});
|
||||
|
||||
it('serves style.css on HTTP GET /style.css', async () => {
|
||||
const res = await fetch(`http://127.0.0.1:${TEST_PORT}/style.css`);
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.headers.get('content-type')).toBe('text/css');
|
||||
});
|
||||
|
||||
it('returns 404 for unknown HTTP path', async () => {
|
||||
const res = await fetch(`http://127.0.0.1:${TEST_PORT}/nonexistent`);
|
||||
expect(res.status).toBe(404);
|
||||
});
|
||||
|
||||
it('returns 404 for path traversal attempt', async () => {
|
||||
const res = await fetch(`http://127.0.0.1:${TEST_PORT}/../../../etc/passwd`);
|
||||
expect(res.status).toBe(404);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user