Einstellungen-Seite: .env-Werte in DB (app_state), keine .env mehr

Neue /einstellungen-Seite (Zahnrad im Header) mit allen bisherigen .env-Werten
(Ollama, E-Mail, CalDAV, REST-API), gespeichert in SQLite (app_state, cfg:-Prefix).
Libs lesen per lib/config.js zur Laufzeit statt beim Start -> Aenderungen
wirken sofort, kein Neustart. Bestehende .env wird beim ersten Start einmalig
migriert.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-13 20:57:31 +02:00
co-authored by Claude
parent 41887dd56c
commit 97b48f9841
12 changed files with 410 additions and 72 deletions
+11 -9
View File
@@ -11,14 +11,12 @@
// replies as text, token by token, so the UI can render progressively.
const promptStore = require('./prompts');
const config = require('./config');
const OLLAMA_HOST = (process.env.OLLAMA_HOST || 'https://ollama.com').replace(/\/+$/, '');
const OLLAMA_MODEL = process.env.OLLAMA_MODEL || 'gpt-oss:120b';
const OLLAMA_TIMEOUT_MS = Number(process.env.OLLAMA_TIMEOUT_MS || 300000);
const MAX_TOOL_ROUNDS = 4;
function isConfigured() {
return Boolean(process.env.OLLAMA_API_KEY);
return Boolean(config.ollama().apiKey);
}
// Stream a single chat completion from Ollama. `messages` = [{role, content}]
@@ -28,8 +26,8 @@ function isConfigured() {
// fires with each incremental text chunk. Returns { content, toolCalls }.
// Aborts cleanly via `signal`.
async function streamChat({ system, messages, tools, onToken, temperature = 0.6, signal }) {
const apiKey = process.env.OLLAMA_API_KEY;
if (!apiKey) throw new Error('OLLAMA_API_KEY ist nicht gesetzt.');
const { host: ollamaHost, model: ollamaModel, apiKey } = config.ollama();
if (!apiKey) throw new Error('OLLAMA_API_KEY ist nicht gesetzt (unter „Einstellungen“ konfigurieren).');
const allMessages = [];
if (system) allMessages.push({ role: 'system', content: system });
@@ -43,7 +41,7 @@ async function streamChat({ system, messages, tools, onToken, temperature = 0.6,
}
const body = {
model: OLLAMA_MODEL,
model: ollamaModel,
stream: true,
options: { temperature },
messages: allMessages,
@@ -52,7 +50,7 @@ async function streamChat({ system, messages, tools, onToken, temperature = 0.6,
let res;
try {
res = await fetch(`${OLLAMA_HOST}/api/chat`, {
res = await fetch(`${ollamaHost}/api/chat`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },
body: JSON.stringify(body),
@@ -216,4 +214,8 @@ function buildContextPrompt(ctx) {
return parts.join('\n\n');
}
module.exports = { isConfigured, streamChat, runChat, buildContextPrompt, OLLAMA_MODEL, MAX_TOOL_ROUNDS };
module.exports = {
isConfigured, streamChat, runChat, buildContextPrompt, MAX_TOOL_ROUNDS,
// Dynamic so an edit on /einstellungen is reflected without a restart.
get OLLAMA_MODEL() { return config.ollama().model; },
};