Restructure chat service, web routes, and add test suite

Split monolithic chat service into modular structure with Matrix client
support, extract web server into per-resource route modules, introduce
bootstrap/main-loop separation, and add comprehensive vitest coverage
across services, repositories, and utilities. Adds project docs and
CLAUDE.md agent instructions.
This commit is contained in:
jjbrunton committed 2026-05-21 01:32:10 +01:00
1 parent dfa0580859
commit 633bb0ec04
84 files changed
+19278 -3888

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
import { Router } from 'express';
import type { WebContext } from '../context.js';
export function createLoginRouter(ctx: WebContext): Router {
const router = Router();
// Info the dashboard uses to decide whether to show the VNC iframe and
// which port to point it at.
router.get('/login/info', (_req, res) => {
const novncPort = parseInt(process.env.NOVNC_PORT ?? '6080', 10);
res.json({
vncEnabled: Boolean(process.env.DISPLAY),
novncPort,
passwordRequired: Boolean(process.env.VNC_PASSWORD),
});
});
router.get('/login/status', async (_req, res) => {
const browser = ctx.services.browser;
if (!browser) {
res.status(503).json({ ready: false, error: 'browser not initialised' });
return;
}
try {
const loggedIn = await browser.isSessionValid();
res.json({ ready: true, loggedIn });
} catch (error) {
ctx.logger.error('Failed to check login status:', error);
res.status(500).json({ ready: true, loggedIn: false, error: 'check failed' });
}
});
// Navigate the headed Chromium running under Xvfb to reddit.com/login so
// the human watching the noVNC stream can complete the flow.
router.post('/login/start', async (_req, res) => {
const browser = ctx.services.browser;
if (!browser) {
res.status(503).json({ ok: false, error: 'browser not initialised' });
return;
}
try {
const page = await browser.getPage();
await page.bringToFront().catch(() => undefined);
await page.goto('https://www.reddit.com/login', { waitUntil: 'domcontentloaded' });
ctx.logger.info('Opened Reddit login page for human completion via VNC');
res.json({ ok: true });
} catch (error) {
ctx.logger.error('Failed to open login page:', error);
res.status(500).json({ ok: false, error: 'navigation failed' });
}
});
return router;
}