import Fastify, { type FastifyInstance } from "fastify"; import cors from "@fastify/cors"; import type { AppConfig } from "./config.js"; import { ThtRunner } from "./tht/tht-runner.js"; import { PiProcessManager } from "./pi/pi-process-manager.js"; import { SseHub } from "./sse/sse-hub.js"; import { authPreHandler } from "./auth/auth.js"; import { sessionRoutes } from "./routes/sessions.js"; import { sqlRoutes } from "./routes/sql.js"; import { metaRoutes, type ListModelsFn } from "./routes/meta.js"; import { settingsRoutes, effectiveSettings } from "./routes/settings.js"; import { createPiModelLister } from "./pi/list-models.js"; import { loadSettings, type Settings } from "./settings/settings-store.js"; export interface BuildAppDeps { thtRunner?: ThtRunner; mgr?: PiProcessManager; spawnFn?: () => any; listModels?: ListModelsFn; getSettings?: () => Settings; } export function buildApp(config: AppConfig, deps?: BuildAppDeps): FastifyInstance { const app = Fastify({ logger: false }); // Allow any origin in dev/e2e; tighten in production via config if needed. app.register(cors, { origin: true, credentials: true, methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], }); const tht = deps?.thtRunner ?? new ThtRunner({ thtBin: config.thtBin, harnessDir: config.harnessDir, configPath: "config/tht.yaml", }); const mgr = deps?.mgr ?? new PiProcessManager(config, deps?.spawnFn ? { spawnFn: deps.spawnFn } : undefined); const hub = new SseHub(); const listModels = deps?.listModels ?? createPiModelLister(config); const getSettings = deps?.getSettings ?? (() => effectiveSettings(config, loadSettings(config))); app.addHook("preHandler", authPreHandler(config.authMode)); app.get("/health", async () => ({ status: "ok" })); sessionRoutes(app, { mgr, tht: tht as ThtRunner, hub, getSettings, ollamaEnsureTimeoutSec: Math.round(config.ollamaEnsureTimeoutMs / 1000), }); sqlRoutes(app, { tht: tht as ThtRunner }); metaRoutes(app, { harnessDir: config.harnessDir, listModels }); settingsRoutes(app, { cfg: config, listModels }); return app; }