improve reasoning toggle tests and refactor model capability checks

This commit is contained in:
2026-09-22 10:31:04 +02:00
parent 3b6c8969cc
commit 7602692341
8 changed files with 777 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
import express from "express";
import multer from "multer";
import {requireLogin} from "../middleware/auth.js";
import {AttachmentError} from "../services/attachmentService.js";
export function createUploadsRouter(service, config) {
const router = express.Router();
const activeUploads = new Map();
const upload = multer({storage: multer.memoryStorage(), limits: {
fileSize: config.uploadMaxSizeMb * 1024 * 1024, files: 1, fields: 0, parts: 1
}}).single("image");
const fail = (res, error) => res.status(error instanceof AttachmentError ? error.status : 500).json({error:
error instanceof AttachmentError ? error.message : "Image operation failed. Please retry."});
router.get("/uploads/config", requireLogin, (_req, res) => res.json({maxSizeMb: config.uploadMaxSizeMb, maxFiles: config.uploadMaxFiles}));
router.post("/uploads", requireLogin, (req, res) => {
const user = req.session.user;
const active = activeUploads.get(user) || 0;
if (active >= config.uploadMaxFiles) return res.status(429).json({error: "Too many simultaneous uploads. Please wait."});
activeUploads.set(user, active + 1);
res.once("close", () => {
const remaining = (activeUploads.get(user) || 1) - 1;
if (remaining) activeUploads.set(user, remaining); else activeUploads.delete(user);
});
upload(req, res, async error => {
if (error) return res.status(error.code === "LIMIT_FILE_SIZE" ? 413 : 400).json({error:
error.code === "LIMIT_FILE_SIZE" ? `Image exceeds ${config.uploadMaxSizeMb} MB` : "Upload one PNG, JPEG or WebP image per request"});
try { res.status(201).json(await service.upload(req.file, req.session.user)); }
catch (failure) { fail(res, failure); }
});
});
router.get("/attachments/:id", requireLogin, async (req, res) => {
try {
const row = service.owned(req.params.id, req.session.user);
const buffer = await service.storage.read(row.storage_key);
res.set({"Content-Type": row.mime_type, "Content-Length": buffer.length, "Cache-Control": "private, no-store",
"X-Content-Type-Options": "nosniff", "Content-Disposition": "inline"}).send(buffer);
} catch (error) { fail(res, error); }
});
router.delete("/attachments/:id", requireLogin, async (req, res) => {
try { await service.remove(req.params.id, req.session.user); res.json({success: true}); }
catch (error) { fail(res, error); }
});
return router;
}