feat: add editable system prompts from web UI

This commit is contained in:
2026-06-04 11:31:56 +02:00
parent ecd75a7fb5
commit f4cb318175
3 changed files with 235 additions and 67 deletions
+68 -2
View File
@@ -26,6 +26,8 @@ import {
buildStylePrompt,
buildSystemPrompt,
buildUserMessage,
setActivePrompts,
DEFAULT_PROMPTS,
} from './server/prompts.mjs';
// ──────────────────────────────────────────────────────────────────────────────
@@ -38,6 +40,7 @@ const PORT = parseInt(process.env.PORT || '3000', 10);
const CORS_ORIGIN = process.env.CORS_ORIGIN || '*';
const DATA_DIR = process.env.DATA_DIR || join(__dirname, 'data');
const HISTORY_FILE = join(DATA_DIR, 'history.json');
const PROMPTS_FILE = join(DATA_DIR, 'prompts.json');
const MAX_HISTORY = 500;
const LLM = {
@@ -58,8 +61,20 @@ if (!LLM.endpoint || !LLM.apiKey) {
// Ensure data directory exists
await mkdir(DATA_DIR, { recursive: true });
console.log(`[startup] LLM endpoint: ${LLM.endpoint}`);
console.log(`[startup] LLM model: ${LLM.model}`);
// Load prompts
try {
const customPromptsStr = await readFile(PROMPTS_FILE, 'utf-8');
const customPrompts = JSON.parse(customPromptsStr);
setActivePrompts(customPrompts);
console.log('[startup] Custom system prompts loaded');
} catch (err) {
if (err.code !== 'ENOENT') {
console.error('[startup] Failed to read prompts.json:', err.message);
}
}
console.log(`[startup] Model: ${LLM.model}`);
console.log(`[startup] Endpoint: ${LLM.endpoint}`);
console.log(`[startup] Data dir: ${DATA_DIR}`);
console.log(`[startup] Listening on: http://0.0.0.0:${PORT}`);
@@ -512,6 +527,45 @@ async function handleGenerate(req, res) {
json(res, { error: lastErr?.message || 'Generation failed' }, 500);
}
// ──────────────────────────────────────────────────────────────────────────────
// System Prompts Config Handlers
// ──────────────────────────────────────────────────────────────────────────────
import { activePrompts } from './server/prompts.mjs';
import { unlink } from 'node:fs/promises';
function handleGetSystemPrompts(req, res) {
json(res, activePrompts);
}
async function handlePostSystemPrompts(req, res) {
try {
const body = await parseJsonBody(req);
// Merge with defaults to ensure all keys exist
const newPrompts = { ...DEFAULT_PROMPTS, ...body };
setActivePrompts(newPrompts);
await writeFile(PROMPTS_FILE, JSON.stringify(newPrompts, null, 2), 'utf-8');
json(res, { success: true });
} catch (err) {
console.error('[prompts] failed to save', err);
json(res, { error: 'Failed to save prompts' }, 500);
}
}
async function handleDeleteSystemPrompts(req, res) {
try {
try {
await unlink(PROMPTS_FILE);
} catch (e) {
if (e.code !== 'ENOENT') throw e;
}
setActivePrompts(DEFAULT_PROMPTS);
json(res, { success: true });
} catch (err) {
console.error('[prompts] failed to delete', err);
json(res, { error: 'Failed to restore default prompts' }, 500);
}
}
// ──────────────────────────────────────────────────────────────────────────────
// Server
// ──────────────────────────────────────────────────────────────────────────────
@@ -532,6 +586,18 @@ const server = createServer(async (req, res) => {
if (req.method === 'GET' && req.url.split('?')[0] === '/api/config') {
return handleConfig(req, res);
}
// System Prompts endpoints
if (req.method === 'GET' && req.url.split('?')[0] === '/api/system-prompts') {
return handleGetSystemPrompts(req, res);
}
if (req.method === 'POST' && req.url.split('?')[0] === '/api/system-prompts') {
return handlePostSystemPrompts(req, res);
}
if (req.method === 'DELETE' && req.url.split('?')[0] === '/api/system-prompts') {
return handleDeleteSystemPrompts(req, res);
}
if (req.method === 'POST' && req.url.split('?')[0] === '/api/generate') {
return handleGenerate(req, res);
}