import type { FastifyInstance } from "fastify"; import type { AppConfig } from "../config.js"; import { loadSettings, saveSettings, type Settings } from "../settings/settings-store.js"; import { listWorkspaces, type ListModelsFn } from "./meta.js"; /** Merge stored settings over env/first-workspace defaults. */ export function effectiveSettings(cfg: AppConfig, stored: Settings): Settings { const workspaces = listWorkspaces(cfg.harnessDir); return { workspace: stored.workspace ?? (workspaces[0]?.name), provider: stored.provider ?? cfg.defaults.provider, model: stored.model ?? cfg.defaults.model, thinking: stored.thinking ?? cfg.defaults.thinking, }; } export function settingsRoutes( app: FastifyInstance, deps: { cfg: AppConfig; listModels: ListModelsFn }, ): void { app.get("/settings", async () => { return effectiveSettings(deps.cfg, loadSettings(deps.cfg)); }); app.put("/settings", async (req, reply) => { const b = (req.body ?? {}) as Settings; if (b.model) { let available: { id: string }[] = []; try { available = await deps.listModels(); } catch { available = []; } // Only validate when Pi gave us a non-empty list; otherwise allow (degraded). if (available.length > 0 && !available.some((m) => m.id === b.model)) { return reply.code(400).send({ error: `Unknown model: ${b.model}` }); } } const next: Settings = { workspace: b.workspace, provider: b.provider, model: b.model, thinking: b.thinking, }; saveSettings(deps.cfg, next); return effectiveSettings(deps.cfg, next); }); }