125 lines
3.9 KiB
TypeScript
125 lines
3.9 KiB
TypeScript
import { NextFunction, Request, Response, Router } from "express";
|
|
import { SHARED_LLM_CONNECTION_FILE } from "../config";
|
|
import { ok } from "../utils/http";
|
|
import { ensureDir, readJsonFile, writeJsonFile } from "../utils/files";
|
|
import path from "path";
|
|
|
|
type LlmProvider = "openai" | "local";
|
|
|
|
interface SharedLlmConnectionRecord {
|
|
schema_version: "shared_llm_connection_v1";
|
|
updated_at: string;
|
|
connection: {
|
|
llmProvider: LlmProvider;
|
|
model: string;
|
|
baseUrl: string;
|
|
temperature: number;
|
|
maxOutputTokens: number;
|
|
};
|
|
}
|
|
|
|
function sanitizeString(value: unknown, fallback: string): string {
|
|
if (typeof value !== "string") {
|
|
return fallback;
|
|
}
|
|
const trimmed = value.trim();
|
|
return trimmed.length > 0 ? trimmed : fallback;
|
|
}
|
|
|
|
function sanitizeNumber(value: unknown, fallback: number): number {
|
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
return value;
|
|
}
|
|
if (typeof value === "string" && value.trim().length > 0) {
|
|
const parsed = Number(value);
|
|
if (Number.isFinite(parsed)) {
|
|
return parsed;
|
|
}
|
|
}
|
|
return fallback;
|
|
}
|
|
|
|
function buildFallbackRecord(): SharedLlmConnectionRecord {
|
|
return {
|
|
schema_version: "shared_llm_connection_v1",
|
|
updated_at: "",
|
|
connection: {
|
|
llmProvider: "local",
|
|
model: "qwen2.5-14b-instruct-1m",
|
|
baseUrl: "http://127.0.0.1:1234/v1",
|
|
temperature: 0,
|
|
maxOutputTokens: 900
|
|
}
|
|
};
|
|
}
|
|
|
|
function loadSharedRecord(): SharedLlmConnectionRecord | null {
|
|
const fallback = buildFallbackRecord();
|
|
const parsed = readJsonFile<SharedLlmConnectionRecord | null>(SHARED_LLM_CONNECTION_FILE, null);
|
|
if (!parsed || typeof parsed !== "object" || !("connection" in parsed) || !parsed.connection) {
|
|
return null;
|
|
}
|
|
const connection = parsed.connection;
|
|
return {
|
|
schema_version: "shared_llm_connection_v1",
|
|
updated_at: sanitizeString(parsed.updated_at, ""),
|
|
connection: {
|
|
llmProvider: connection.llmProvider === "local" ? "local" : "openai",
|
|
model: sanitizeString(connection.model, fallback.connection.model),
|
|
baseUrl: sanitizeString(connection.baseUrl, fallback.connection.baseUrl),
|
|
temperature: sanitizeNumber(connection.temperature, fallback.connection.temperature),
|
|
maxOutputTokens: Math.max(1, Math.trunc(sanitizeNumber(connection.maxOutputTokens, fallback.connection.maxOutputTokens)))
|
|
}
|
|
};
|
|
}
|
|
|
|
export function buildSharedLlmConfigRouter(): Router {
|
|
const router = Router();
|
|
|
|
router.get("/api/llm/shared-connection", (_req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const record = loadSharedRecord();
|
|
ok(res, {
|
|
ok: true,
|
|
connection: record?.connection ?? null,
|
|
updated_at: record?.updated_at ?? null,
|
|
exists: Boolean(record)
|
|
});
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
router.post("/api/llm/shared-connection", (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const body = (req.body ?? {}) as Record<string, unknown>;
|
|
const fallback = buildFallbackRecord();
|
|
const record: SharedLlmConnectionRecord = {
|
|
schema_version: "shared_llm_connection_v1",
|
|
updated_at: new Date().toISOString(),
|
|
connection: {
|
|
llmProvider: body.llmProvider === "local" ? "local" : "openai",
|
|
model: sanitizeString(body.model, fallback.connection.model),
|
|
baseUrl: sanitizeString(body.baseUrl, fallback.connection.baseUrl),
|
|
temperature: sanitizeNumber(body.temperature, fallback.connection.temperature),
|
|
maxOutputTokens: Math.max(
|
|
1,
|
|
Math.trunc(sanitizeNumber(body.maxOutputTokens, fallback.connection.maxOutputTokens))
|
|
)
|
|
}
|
|
};
|
|
ensureDir(path.dirname(SHARED_LLM_CONNECTION_FILE));
|
|
writeJsonFile(SHARED_LLM_CONNECTION_FILE, record);
|
|
ok(res, {
|
|
ok: true,
|
|
connection: record.connection,
|
|
updated_at: record.updated_at
|
|
});
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
return router;
|
|
}
|