104 lines
3.3 KiB
TypeScript
104 lines
3.3 KiB
TypeScript
// server/utils/userConfig.ts - 用户自定义配置 JSON value 的归一化与合并
|
|
import type { Prisma } from "~~/prisma/generated/client";
|
|
import type { IUserSettingsUpdateRequest } from "~~/shared/types/settings";
|
|
|
|
export interface UserConfigValue {
|
|
useCustomConfig: boolean;
|
|
customApiBase: string | null;
|
|
customApiKey: string | null;
|
|
customModel: string | null;
|
|
customMaxTokens: number | null;
|
|
customTemperature: number | null;
|
|
}
|
|
|
|
export const DEFAULT_USER_CONFIG_VALUE: UserConfigValue = {
|
|
useCustomConfig: false,
|
|
customApiBase: null,
|
|
customApiKey: null,
|
|
customModel: null,
|
|
customMaxTokens: null,
|
|
customTemperature: null
|
|
};
|
|
|
|
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
typeof value === "object" && value !== null && !Array.isArray(value);
|
|
|
|
const cleanString = (value: unknown): string | null => {
|
|
if (typeof value !== "string") return null;
|
|
const trimmed = value.trim();
|
|
return trimmed.length > 0 ? trimmed : null;
|
|
};
|
|
|
|
const cleanApiKey = (value: unknown): string | null => {
|
|
if (typeof value !== "string") return null;
|
|
return value.length > 0 ? value : null;
|
|
};
|
|
|
|
const cleanNumber = (value: unknown): number | null =>
|
|
typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
|
|
export const normalizeUserConfigValue = (
|
|
value: unknown
|
|
): UserConfigValue => {
|
|
if (!isRecord(value)) {
|
|
return { ...DEFAULT_USER_CONFIG_VALUE };
|
|
}
|
|
|
|
return {
|
|
useCustomConfig: value.useCustomConfig === true,
|
|
customApiBase: cleanString(value.customApiBase),
|
|
customApiKey: cleanApiKey(value.customApiKey),
|
|
customModel: cleanString(value.customModel),
|
|
customMaxTokens: cleanNumber(value.customMaxTokens),
|
|
customTemperature: cleanNumber(value.customTemperature)
|
|
};
|
|
};
|
|
|
|
export const mergeUserConfigUpdate = (
|
|
current: UserConfigValue,
|
|
req: IUserSettingsUpdateRequest
|
|
): UserConfigValue => {
|
|
const next: UserConfigValue = { ...current };
|
|
|
|
if (req.useCustomConfig !== undefined) {
|
|
next.useCustomConfig = req.useCustomConfig;
|
|
}
|
|
if (req.customApiBase !== undefined) {
|
|
next.customApiBase = cleanString(req.customApiBase);
|
|
}
|
|
// 空字符串表示不修改已保存的 key,避免用户保存表单时误清空密钥
|
|
if (req.customApiKey !== undefined && req.customApiKey !== "") {
|
|
next.customApiKey = cleanApiKey(req.customApiKey);
|
|
}
|
|
if (req.customModel !== undefined) {
|
|
next.customModel = cleanString(req.customModel);
|
|
}
|
|
if (req.customMaxTokens !== undefined) {
|
|
next.customMaxTokens = cleanNumber(req.customMaxTokens);
|
|
}
|
|
if (req.customTemperature !== undefined) {
|
|
next.customTemperature = cleanNumber(req.customTemperature);
|
|
}
|
|
|
|
return next;
|
|
};
|
|
|
|
export const hasUserConfigMutation = (req: IUserSettingsUpdateRequest) =>
|
|
req.useCustomConfig !== undefined ||
|
|
req.customApiBase !== undefined ||
|
|
(req.customApiKey !== undefined && req.customApiKey !== "") ||
|
|
req.customModel !== undefined ||
|
|
req.customMaxTokens !== undefined ||
|
|
req.customTemperature !== undefined;
|
|
|
|
export const toUserConfigJson = (
|
|
value: UserConfigValue
|
|
): Prisma.InputJsonObject => ({
|
|
useCustomConfig: value.useCustomConfig,
|
|
customApiBase: value.customApiBase,
|
|
customApiKey: value.customApiKey,
|
|
customModel: value.customModel,
|
|
customMaxTokens: value.customMaxTokens,
|
|
customTemperature: value.customTemperature
|
|
});
|