UNPKG

lynkr

Version:

Self-hosted LLM gateway and tier-routing proxy for Claude Code, Cursor, and Codex. Routes across Ollama, AWS Bedrock, OpenRouter, Databricks, Azure OpenAI, llama.cpp, and LM Studio with prompt caching, MCP tools, and 60-80% cost savings.

82 lines (70 loc) 2.99 kB
const express = require("express"); const logger = require("../logger"); const fileStore = require("../stores/file-store"); const router = express.Router(); const MAX_FILE_SIZE = parseInt(process.env.FILES_MAX_SIZE_MB || "100", 10) * 1024 * 1024; router.post("/files", async (req, res) => { try { const chunks = []; let totalSize = 0; for await (const chunk of req) { totalSize += chunk.length; if (totalSize > MAX_FILE_SIZE) { return res.status(413).json({ error: { message: `File exceeds ${MAX_FILE_SIZE / 1024 / 1024}MB limit` } }); } chunks.push(chunk); } const buffer = Buffer.concat(chunks); const contentType = req.headers["content-type"] || ""; let filename = "upload"; let purpose = "assistants"; let mimeType = "application/octet-stream"; if (contentType.includes("multipart/form-data")) { const boundary = contentType.split("boundary=")[1]; if (boundary) { const { parseMultipart } = require("./files-multipart"); const parsed = parseMultipart(buffer, boundary); if (parsed.file) { filename = parsed.filename || filename; mimeType = parsed.mimeType || mimeType; purpose = parsed.purpose || purpose; const entry = await fileStore.storeFile(parsed.file, { filename, purpose, mimeType }); return res.json(entry); } } } // Raw body upload mimeType = contentType.split(";")[0].trim() || mimeType; filename = req.headers["x-filename"] || filename; purpose = req.query.purpose || purpose; const entry = await fileStore.storeFile(buffer, { filename, purpose, mimeType }); res.json(entry); } catch (err) { logger.error({ err }, "File upload failed"); res.status(500).json({ error: { message: err.message } }); } }); router.get("/files", (req, res) => { const files = fileStore.listFiles({ purpose: req.query.purpose }); res.json({ object: "list", data: files }); }); router.get("/files/:id", (req, res) => { const file = fileStore.getFile(req.params.id); if (!file) return res.status(404).json({ error: { message: "File not found" } }); res.json(file); }); router.get("/files/:id/content", async (req, res) => { const file = fileStore.getFile(req.params.id); if (!file) return res.status(404).json({ error: { message: "File not found" } }); const content = await fileStore.getFileContent(req.params.id); if (!content) return res.status(404).json({ error: { message: "File content not found" } }); res.setHeader("Content-Type", file.mime_type); res.setHeader("Content-Disposition", `attachment; filename="${file.filename}"`); res.send(content); }); router.delete("/files/:id", async (req, res) => { const deleted = await fileStore.deleteFile(req.params.id); if (!deleted) return res.status(404).json({ error: { message: "File not found" } }); res.json({ id: req.params.id, object: "file", deleted: true }); }); module.exports = router;