71 lines
2.7 KiB
TypeScript
71 lines
2.7 KiB
TypeScript
import type Database from "bun:sqlite";
|
|
|
|
import type { CreateModelRequest, RuntimeMode } from "../../../shared/api";
|
|
import type { Logger } from "../../logger";
|
|
|
|
import { MODEL_CAPABILITIES } from "../../../shared/api";
|
|
import { createModel } from "../../db/models";
|
|
import { createApiError, jsonResponse } from "../../helpers";
|
|
|
|
export async function handleCreateModel(
|
|
req: Request,
|
|
db: Database,
|
|
mode: RuntimeMode,
|
|
logger: Logger,
|
|
): Promise<Response> {
|
|
let body: CreateModelRequest;
|
|
try {
|
|
body = (await req.json()) as CreateModelRequest;
|
|
} catch (e: unknown) {
|
|
logger.warn({ error: e instanceof Error ? e.message : String(e) }, "请求 JSON 解析失败");
|
|
return jsonResponse(createApiError("Invalid JSON body", 400), { mode, status: 400 });
|
|
}
|
|
|
|
if (!body.name || typeof body.name !== "string") {
|
|
return jsonResponse(createApiError("name is required", 400), { mode, status: 400 });
|
|
}
|
|
|
|
if (!body.modelId || typeof body.modelId !== "string") {
|
|
return jsonResponse(createApiError("modelId is required", 400), { mode, status: 400 });
|
|
}
|
|
|
|
if (!body.providerId || typeof body.providerId !== "string") {
|
|
return jsonResponse(createApiError("providerId is required", 400), { mode, status: 400 });
|
|
}
|
|
|
|
if (!Array.isArray(body.capabilities) || body.capabilities.length === 0) {
|
|
return jsonResponse(createApiError("capabilities is required and must be a non-empty array", 400), {
|
|
mode,
|
|
status: 400,
|
|
});
|
|
}
|
|
|
|
const invalidCaps = body.capabilities.filter((c) => !MODEL_CAPABILITIES.includes(c));
|
|
if (invalidCaps.length > 0) {
|
|
return jsonResponse(createApiError(`Invalid capabilities: ${invalidCaps.join(", ")}`, 400), { mode, status: 400 });
|
|
}
|
|
|
|
const numberError = validateOptionalPositiveInteger("contextLength", body.contextLength);
|
|
if (numberError) return jsonResponse(createApiError(numberError, 400), { mode, status: 400 });
|
|
|
|
const tokenError = validateOptionalPositiveInteger("maxOutputTokens", body.maxOutputTokens);
|
|
if (tokenError) return jsonResponse(createApiError(tokenError, 400), { mode, status: 400 });
|
|
|
|
const result = createModel(db, body, logger);
|
|
if ("error" in result) {
|
|
return jsonResponse(createApiError(result.error, result.status), { mode, status: result.status });
|
|
}
|
|
|
|
logger.info(
|
|
{ modelId: result.model.id, name: result.model.name, providerId: result.model.providerId },
|
|
"模型创建成功",
|
|
);
|
|
return jsonResponse(result, { mode, status: 201 });
|
|
}
|
|
|
|
function validateOptionalPositiveInteger(field: string, value: null | number | undefined): null | string {
|
|
if (value === undefined || value === null) return null;
|
|
if (!Number.isInteger(value) || value <= 0) return `${field} must be a positive integer`;
|
|
return null;
|
|
}
|