Rl-Auto / apps /web-legacy /src /settings.ts
Lazywords's picture
Deploy RL Auto Docker Space
c4ae742
Raw
History Blame Contribute Delete
4.86 kB
import type { AppSettings, ApiMode, SavedModelCredential } from "./types";
const SETTINGS_KEY = "task-polisher.settings.v3";
const LEGACY_SETTINGS_KEY = "task-polisher.settings.v2";
export const MODEL_OPTIONS = [
"deepseek-v4-pro",
"gpt-5.4",
"gpt-5.3-codex",
"gpt-5",
"gpt-5-codex",
"z-ai/glm-5.1",
"custom",
];
export const DEFAULT_SETTINGS: AppSettings = {
ruleProfile: "echo-05061347",
polishTransport: "browser",
analysisTransport: "backend",
apiMode: "chat",
baseURL: "https://api.deepseek.com",
apiKey: "",
savedModelCredentials: [],
selectedModelCredentialId: "",
modelPreset: "deepseek-v4-pro",
customModel: "",
concurrency: 3,
temperature: 0.7,
topP: 1,
maxTokens: 32768,
enableThinking: true,
clearThinking: false,
};
export function resolveModel(settings: AppSettings): string {
return settings.modelPreset === "custom" ? settings.customModel.trim() : settings.modelPreset;
}
export function defaultBaseURLForMode(_apiMode: ApiMode): string {
return "https://api.deepseek.com";
}
export function applyDeepSeekPreset(settings: AppSettings): AppSettings {
return sanitizeSettings({
...settings,
apiMode: "chat",
baseURL: "https://api.deepseek.com",
selectedModelCredentialId: "",
modelPreset: "deepseek-v4-pro",
customModel: "",
temperature: 0.7,
topP: 1,
maxTokens: 32768,
enableThinking: true,
clearThinking: false,
});
}
export function loadSettings(): AppSettings {
const stored = readJson(SETTINGS_KEY) ?? readJson(LEGACY_SETTINGS_KEY) ?? {};
return sanitizeSettings({ ...DEFAULT_SETTINGS, ...stored });
}
export function saveSettings(settings: AppSettings): AppSettings {
const sanitized = sanitizeSettings(settings);
window.localStorage.setItem(SETTINGS_KEY, JSON.stringify(sanitized));
return sanitized;
}
export function sanitizeSettings(raw: Partial<AppSettings>): AppSettings {
const apiMode = raw.apiMode === "responses" ? "responses" : "chat";
const modelPreset = MODEL_OPTIONS.includes(String(raw.modelPreset)) ? String(raw.modelPreset) : DEFAULT_SETTINGS.modelPreset;
const customModel = modelPreset === "custom" ? String(raw.customModel || "").trim() : "";
const baseURL = String(raw.baseURL || DEFAULT_SETTINGS.baseURL).trim() || defaultBaseURLForMode(apiMode);
const apiKey = String(raw.apiKey || "").trim();
const savedModelCredentials = sanitizeSavedModelCredentials(raw.savedModelCredentials);
const selectedModelCredentialId = savedModelCredentials.some((item) => item.id === raw.selectedModelCredentialId)
? String(raw.selectedModelCredentialId)
: "";
return {
ruleProfile: String(raw.ruleProfile || DEFAULT_SETTINGS.ruleProfile),
polishTransport: "browser",
analysisTransport: "backend",
apiMode,
baseURL,
apiKey,
savedModelCredentials,
selectedModelCredentialId,
modelPreset,
customModel,
concurrency: clampInteger(raw.concurrency, 1, 8, DEFAULT_SETTINGS.concurrency),
temperature: clampNumber(raw.temperature, 0, 2, DEFAULT_SETTINGS.temperature),
topP: clampNumber(raw.topP, 0, 1, DEFAULT_SETTINGS.topP),
maxTokens: clampInteger(raw.maxTokens, 1, 131072, DEFAULT_SETTINGS.maxTokens),
enableThinking: raw.enableThinking !== false,
clearThinking: Boolean(raw.clearThinking),
};
}
function sanitizeSavedModelCredentials(value: unknown): SavedModelCredential[] {
if (!Array.isArray(value)) return [];
const seen = new Set<string>();
return value
.map((item, index) => {
const raw = item as Partial<SavedModelCredential>;
const baseURL = String(raw?.baseURL || "").trim();
const apiKey = String(raw?.apiKey || "").trim();
if (!baseURL || !apiKey) return null;
const id = String(raw?.id || "").trim() || makeCredentialId(baseURL, index);
if (seen.has(id)) return null;
seen.add(id);
return {
id,
name: String(raw?.name || "").trim() || baseURL,
baseURL,
apiKey,
};
})
.filter((item): item is SavedModelCredential => Boolean(item));
}
function makeCredentialId(baseURL: string, index: number): string {
return `credential-${index}-${baseURL.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || "model"}`;
}
function clampNumber(value: unknown, min: number, max: number, fallback: number): number {
const parsed = Number(value);
if (!Number.isFinite(parsed)) return fallback;
return Math.min(max, Math.max(min, parsed));
}
function clampInteger(value: unknown, min: number, max: number, fallback: number): number {
return Math.round(clampNumber(value, min, max, fallback));
}
function readJson(key: string): Record<string, unknown> | null {
try {
const raw = window.localStorage.getItem(key);
return raw ? JSON.parse(raw) : null;
} catch {
return null;
}
}