feat: Runtime-Config via Diagnostic UI — kein .env-Sync mehr
Framework fuer zentrale Runtime-Konfiguration: - /api/runtime-config (GET/POST) persistiert in /shared/config/runtime.json - Werte haben Vorrang ueber die ENV-Variablen aus aria.env - Feldliste: RVS_HOST/PORT/TLS/TOKEN, ARIA_AUTH_TOKEN, WHISPER_MODEL/LANGUAGE - Atomic write (tmp + rename) fuer Konsistenz Bridge: - load_config() liest nach aria.env noch runtime.json und ueberschreibt die Werte. Aenderungen werden beim Neustart der Bridge uebernommen. Diagnostic UI: - Neue Sektion "Runtime-Konfiguration" in Einstellungen - Formular fuer RVS-Credentials + Aria-Auth-Token - "Speichern" persistiert, triggert auch QR-Code-Regenerierung - Hinweis: Diagnostic-Container selbst bleibt auf ENV (erstmal) issue.md konsolidiert — 6 groessere Tasks dieser Session als erledigt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,41 @@ let activeSessionKey = (() => {
|
||||
return "main";
|
||||
})();
|
||||
|
||||
// ── Runtime-Config: /shared/config/runtime.json ─────────────
|
||||
// ENV-Werte sind Defaults; Werte aus runtime.json haben Vorrang.
|
||||
// Bridge und ggf. andere Komponenten lesen dieselbe Datei.
|
||||
const RUNTIME_CONFIG_FILE = "/shared/config/runtime.json";
|
||||
const RUNTIME_CONFIG_FIELDS = [
|
||||
"RVS_HOST", "RVS_PORT", "RVS_TLS", "RVS_TOKEN",
|
||||
"ARIA_AUTH_TOKEN", "WHISPER_MODEL", "WHISPER_LANGUAGE",
|
||||
];
|
||||
function readRuntimeConfig() {
|
||||
const envDefaults = {
|
||||
RVS_HOST, RVS_PORT, RVS_TLS, RVS_TOKEN,
|
||||
ARIA_AUTH_TOKEN: process.env.ARIA_AUTH_TOKEN || "",
|
||||
WHISPER_MODEL: process.env.WHISPER_MODEL || "medium",
|
||||
WHISPER_LANGUAGE: process.env.WHISPER_LANGUAGE || "de",
|
||||
};
|
||||
try {
|
||||
const raw = fs.readFileSync(RUNTIME_CONFIG_FILE, "utf-8");
|
||||
const parsed = JSON.parse(raw);
|
||||
return { ...envDefaults, ...parsed };
|
||||
} catch {
|
||||
return envDefaults;
|
||||
}
|
||||
}
|
||||
function writeRuntimeConfig(patch) {
|
||||
let current = {};
|
||||
try { current = JSON.parse(fs.readFileSync(RUNTIME_CONFIG_FILE, "utf-8")); } catch {}
|
||||
for (const key of Object.keys(patch)) {
|
||||
if (RUNTIME_CONFIG_FIELDS.includes(key)) current[key] = patch[key];
|
||||
}
|
||||
fs.mkdirSync("/shared/config", { recursive: true });
|
||||
const tmp = RUNTIME_CONFIG_FILE + ".tmp";
|
||||
fs.writeFileSync(tmp, JSON.stringify(current, null, 2));
|
||||
fs.renameSync(tmp, RUNTIME_CONFIG_FILE);
|
||||
}
|
||||
|
||||
// Atomic write: temp-file + rename, laute Logs bei Fehler.
|
||||
function persistActiveSession(key) {
|
||||
try {
|
||||
@@ -1169,6 +1204,26 @@ const server = http.createServer((req, res) => {
|
||||
} else if (req.url === "/api/session") {
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify({ sessionKey: activeSessionKey }));
|
||||
} else if (req.url === "/api/runtime-config" && req.method === "GET") {
|
||||
// Zentrale Runtime-Config (ENV + Override aus /shared/config/runtime.json)
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify(readRuntimeConfig()));
|
||||
} else if (req.url === "/api/runtime-config" && req.method === "POST") {
|
||||
let body = "";
|
||||
req.on("data", chunk => { body += chunk; if (body.length > 32768) req.destroy(); });
|
||||
req.on("end", () => {
|
||||
try {
|
||||
const patch = JSON.parse(body);
|
||||
writeRuntimeConfig(patch);
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify({ ok: true, config: readRuntimeConfig() }));
|
||||
log("info", "server", `Runtime-Config aktualisiert: ${Object.keys(patch).join(", ")}`);
|
||||
} catch (err) {
|
||||
res.writeHead(400, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify({ ok: false, error: err.message }));
|
||||
}
|
||||
});
|
||||
return;
|
||||
} else if (req.url === "/api/onboarding") {
|
||||
// RVS-Credentials fuer QR-Code App-Onboarding
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
|
||||
Reference in New Issue
Block a user