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

+11
View File
@@ -7,6 +7,7 @@ import fs from 'fs';
export class BrowserClient {
private context: BrowserContext | null = null;
private sessionDir: string | null = null;
private sessionValidityInFlight: Promise<boolean> | null = null;
constructor(
private config: Config,
@@ -59,6 +60,16 @@ export class BrowserClient {
}
async isSessionValid(): Promise<boolean> {
if (this.sessionValidityInFlight) {
return this.sessionValidityInFlight;
}
this.sessionValidityInFlight = this.doSessionValidityCheck().finally(() => {
this.sessionValidityInFlight = null;
});
return this.sessionValidityInFlight;
}
private async doSessionValidityCheck(): Promise<boolean> {
try {
const page = await this.getPage();
await page.goto('https://www.reddit.com', { waitUntil: 'domcontentloaded', timeout: 30000 });
-29
View File
@@ -1,29 +0,0 @@
import type { Page } from 'playwright';
import type { Logger } from '../utils/logger.js';
import type { MediaDownloadResult, MediaDownloader } from '../services/media.js';
export class PlaywrightMediaDownloader implements MediaDownloader {
constructor(
private page: Page,
private logger: Logger
) {}
async fetch(url: string): Promise<MediaDownloadResult | null> {
try {
const response = await this.page.request.get(url, { timeout: 15000 });
if (!response.ok()) {
this.logger.warn(`Media download failed (${response.status()}): ${url}`);
return null;
}
const headers = response.headers();
const contentType = headers['content-type'] ?? null;
const buffer = Buffer.from(await response.body());
return { buffer, contentType };
} catch (error) {
this.logger.warn(`Media download error for ${url}:`, error);
return null;
}
}
}