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:
+16
-18
@@ -11,6 +11,7 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const promptStore = require('./prompts');
|
||||
const designStore = require('./design');
|
||||
const config = require('./config');
|
||||
|
||||
// Embedded typefaces (all SIL Open Font License — see lib/fonts/OFL*.txt):
|
||||
// Lato — the classic layout's workhorse
|
||||
@@ -47,10 +48,8 @@ function makeDoc(t) {
|
||||
return doc;
|
||||
}
|
||||
|
||||
// Ollama Cloud API (https://ollama.com). Override host/model via env if needed.
|
||||
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);
|
||||
// Ollama Cloud API (https://ollama.com). Host/model/timeout come from the DB
|
||||
// (editable via /einstellungen) and are read fresh per call via config.ollama().
|
||||
|
||||
// ===========================================================================
|
||||
// 1. LLM call — produce tailored TEXT for the template
|
||||
@@ -177,12 +176,11 @@ function buildOutputSchema(dokumente) {
|
||||
|
||||
async function generateTailoredTexts({ job, basisDokumente, settings, llmNotizen = '', zusatzAnlagen = [], prompts = null, dokumente = null }) {
|
||||
const doks = normalizeDokumente(dokumente);
|
||||
const apiKey = process.env.OLLAMA_API_KEY;
|
||||
const { host: ollamaHost, model: ollamaModel, timeoutMs: ollamaTimeoutMs, apiKey } = config.ollama();
|
||||
if (!apiKey) {
|
||||
throw new Error(
|
||||
'OLLAMA_API_KEY ist nicht gesetzt. Bitte den API-Schlüssel als ' +
|
||||
'Umgebungsvariable (z. B. in einer .env-Datei) hinterlegen, damit ' +
|
||||
'Bewerbungsunterlagen generiert werden können.'
|
||||
'Kein Ollama-API-Schlüssel konfiguriert. Bitte unter „Einstellungen“ den ' +
|
||||
'API-Schlüssel eintragen, damit Bewerbungsunterlagen generiert werden können.'
|
||||
);
|
||||
}
|
||||
if (!basisDokumente || basisDokumente.length === 0) {
|
||||
@@ -428,15 +426,15 @@ async function generateTailoredTexts({ job, basisDokumente, settings, llmNotizen
|
||||
`JSON-Objekt, ohne Markdown, ohne Code-Fences, ohne weiteren Text.`;
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), OLLAMA_TIMEOUT_MS);
|
||||
const timeout = setTimeout(() => controller.abort(), ollamaTimeoutMs);
|
||||
|
||||
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({
|
||||
model: OLLAMA_MODEL,
|
||||
model: ollamaModel,
|
||||
stream: false,
|
||||
format: buildOutputSchema(doks),
|
||||
options: { temperature: 0.4 },
|
||||
@@ -449,7 +447,7 @@ async function generateTailoredTexts({ job, basisDokumente, settings, llmNotizen
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.name === 'AbortError') {
|
||||
throw new Error(`Zeitüberschreitung bei der KI-Anfrage (> ${Math.round(OLLAMA_TIMEOUT_MS / 1000)}s).`);
|
||||
throw new Error(`Zeitüberschreitung bei der KI-Anfrage (> ${Math.round(ollamaTimeoutMs / 1000)}s).`);
|
||||
}
|
||||
throw new Error(`Verbindung zur Ollama-API fehlgeschlagen: ${err.message}`);
|
||||
} finally {
|
||||
@@ -1942,17 +1940,17 @@ async function generateApplicationDocuments({ job, basisDokumente, settings, zus
|
||||
|
||||
// Small shared Ollama JSON call (used by the reply drafter).
|
||||
async function ollamaChatJSON({ system, user, schema, temperature = 0.5 }) {
|
||||
const apiKey = process.env.OLLAMA_API_KEY;
|
||||
if (!apiKey) throw new Error('OLLAMA_API_KEY ist nicht gesetzt.');
|
||||
const { host: ollamaHost, model: ollamaModel, timeoutMs: ollamaTimeoutMs, apiKey } = config.ollama();
|
||||
if (!apiKey) throw new Error('Kein Ollama-API-Schlüssel konfiguriert (unter „Einstellungen“ eintragen).');
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), OLLAMA_TIMEOUT_MS);
|
||||
const timeout = setTimeout(() => controller.abort(), ollamaTimeoutMs);
|
||||
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({
|
||||
model: OLLAMA_MODEL,
|
||||
model: ollamaModel,
|
||||
stream: false,
|
||||
format: schema,
|
||||
options: { temperature },
|
||||
@@ -1964,7 +1962,7 @@ async function ollamaChatJSON({ system, user, schema, temperature = 0.5 }) {
|
||||
signal: controller.signal,
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.name === 'AbortError') throw new Error(`Zeitüberschreitung bei der KI-Anfrage (> ${Math.round(OLLAMA_TIMEOUT_MS / 1000)}s).`);
|
||||
if (err.name === 'AbortError') throw new Error(`Zeitüberschreitung bei der KI-Anfrage (> ${Math.round(ollamaTimeoutMs / 1000)}s).`);
|
||||
throw new Error(`Verbindung zur Ollama-API fehlgeschlagen: ${err.message}`);
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
|
||||
Reference in New Issue
Block a user