feat(diagnostic): Anhang-Limit einstellbar + Datum/Uhrzeit bei Gedanken

Zwei Dinge, die bisher nur im Code bzw. nur in der DB standen.

Anhang-Limit (Einstellungen → System & Wartung):
- Das Limit war eine Env-Variable mit 20 MB Default — zum Anheben musste man
  die .env editieren und das Brain neu starten. Jetzt steht es in runtime.json
  und das Brain liest es bei JEDEM Upload neu: Aenderung greift sofort.
- Reihenfolge: runtime.json > ENV > Default. Anders als beim OpenAI-Endpunkt
  gewinnt hier NICHT die .env — dort erzwingt ein Docker-Port-Mapping das,
  hier gibt es keinen solchen Zwang, und eine Einstellung die nichts tut waere
  schlimmer als keine.
- Default von 20 auf 64 MB. Genau so viel holt die App auch auf ausdruecklichen
  Tipp noch herunter (TAP_DL_MAX_BYTES); darueber warnt die UI, verbietet es
  aber nicht — der Anhang liegt dann sauber auf dem Server, ist mobil nur nicht
  mehr ladbar.
- Neuer Endpunkt GET /attachments/limit. Das fest eingetippte "max 20 MB pro
  Datei" im HTML ist weg — es stimmte nach jeder Aenderung nicht mehr.
- Die Fehlermeldung nennt jetzt MB statt Bytes und sagt, wo die Einstellung ist.

Datum/Uhrzeit bei Gedanken:
- created_at/updated_at lagen schon immer in der DB und wurden ausgeliefert —
  nur nie angezeigt. Jede Zeile zeigt jetzt "angelegt <Zeit>" und, falls
  abweichend, "geaendert <Zeit>" plus ein relatives "(vor 3 Std)". Damit sieht
  man auf den ersten Blick, was der letzte Eintrag war.
- Sortier-Dropdown: nach Typ gruppiert (wie bisher) oder nach Anlage/Aenderung
  auf- und absteigend. Bei Zeit-Sortierung wird die Liste flach dargestellt —
  man will sehen was zuletzt passiert ist, nicht in welche Schublade es gehoert.
- Zeitraum-Filter (🕒) mit von/bis, umschaltbar zwischen angelegt und geaendert,
  plus Schnellwahl Heute / 7 / 30 Tage. Gilt auch fuer Such-Treffer, damit
  "suche X, aber nur letzte Woche" geht. Zuklappen schaltet ihn aus, und das
  ✕-Zuruecksetzen raeumt ihn mit auf (sonst filtert er unsichtbar weiter).

Beides gegen den echten Code getestet: 7 Faelle fuers Limit (inkl. kaputter
runtime.json und einem 50-MB-PDF an beiden Grenzen), 10 fuer Sortierung und
Zeitraum.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-03 10:33:54 +02:00
co-authored by Claude Opus 5
parent 7b46881677
commit 734868efab
4 changed files with 367 additions and 10 deletions
+77
View File
@@ -268,6 +268,9 @@ const RUNTIME_CONFIG_FIELDS = [
"RVS_HOST", "RVS_PORT", "RVS_TLS", "RVS_TOKEN",
"ARIA_AUTH_TOKEN", "WHISPER_MODEL", "WHISPER_LANGUAGE",
"brainModel",
// Groessen-Limit fuer Memory-Anhaenge in MB. Das Brain liest es pro Upload
// aus derselben Datei — Aenderung greift ohne Neustart.
"memoryAttachmentMaxMb",
];
function readRuntimeConfig() {
const envDefaults = {
@@ -3207,6 +3210,10 @@ wss.on("connection", (ws) => {
handleGetModel(ws);
} else if (msg.action === "set_model") {
handleSetModel(ws, msg.model);
} else if (msg.action === "get_attachment_limit") {
handleGetAttachmentLimit(ws);
} else if (msg.action === "set_attachment_limit") {
handleSetAttachmentLimit(ws, msg.maxMb);
} else if (msg.action === "voice_id_status") {
// An whisper-bridge weiterleiten + Antwort an Browser zurueck
const reqId = `vid_${Date.now().toString(36)}`;
@@ -3629,6 +3636,76 @@ function handleSetModel(clientWs, model) {
return;
}
// ── Einstellungen: Groessen-Limit fuer Memory-Anhaenge ──────────────
// Steht in runtime.json als `memoryAttachmentMaxMb`. Das Brain liest es bei
// JEDEM Upload neu (memory_attachments.max_bytes()) — eine Aenderung greift
// also sofort, ohne aria-brain neu zu starten.
//
// Obergrenze mit Bedacht: der Anhang geht als base64-in-JSON zur App, die muss
// ihn komplett in den Speicher nehmen. Ueber ~64 MB laedt das Handy ihn nicht
// mehr (TAP_DL_MAX_BYTES in ChatScreen.tsx) — dann liegt er zwar sauber auf dem
// Server, ist mobil aber nur noch per Dateimanager erreichbar. Darum warnen wir
// darueber, verbieten es aber nicht.
const ATTACHMENT_LIMIT_SOFT_MB = 64;
const ATTACHMENT_LIMIT_MAX_MB = 1024;
function handleGetAttachmentLimit(clientWs) {
// Das Brain ist die Wahrheit — es kennt auch den ENV-Fallback, den der
// Diagnostic-Container nicht sieht.
const brain = process.env.BRAIN_URL || "http://aria-brain:8080";
const req = http.get(`${brain}/attachments/limit`, { timeout: 5000 }, (r) => {
let body = "";
r.on("data", (c) => { body += c; });
r.on("end", () => {
let maxMb = null;
try { maxMb = JSON.parse(body).maxMb; } catch (_) {}
clientWs.send(JSON.stringify({
type: "attachment_limit_info",
maxMb,
softMb: ATTACHMENT_LIMIT_SOFT_MB,
hardMb: ATTACHMENT_LIMIT_MAX_MB,
error: maxMb == null ? "Brain antwortet nicht verwertbar" : undefined,
}));
});
});
req.on("error", (err) => {
clientWs.send(JSON.stringify({ type: "attachment_limit_info", error: err.message }));
});
req.on("timeout", () => { req.destroy(new Error("Brain antwortet nicht")); });
}
function handleSetAttachmentLimit(clientWs, maxMb) {
const n = Number(maxMb);
if (!isFinite(n) || n <= 0) {
clientWs.send(JSON.stringify({
type: "attachment_limit_info", error: "Bitte eine Zahl groesser 0 angeben (MB)" }));
return;
}
if (n > ATTACHMENT_LIMIT_MAX_MB) {
clientWs.send(JSON.stringify({
type: "attachment_limit_info",
error: `Maximal ${ATTACHMENT_LIMIT_MAX_MB} MB — darueber reisst der WebSocket-Transport` }));
return;
}
try {
writeRuntimeConfig({ memoryAttachmentMaxMb: n });
log("info", "server", `Anhang-Limit gesetzt: ${n} MB`);
clientWs.send(JSON.stringify({
type: "attachment_limit_info",
maxMb: n,
softMb: ATTACHMENT_LIMIT_SOFT_MB,
hardMb: ATTACHMENT_LIMIT_MAX_MB,
info: n > ATTACHMENT_LIMIT_SOFT_MB
? `${n} MB gesetzt (greift sofort). Hinweis: ueber ${ATTACHMENT_LIMIT_SOFT_MB} MB `
+ `laedt die Handy-App Anhaenge nicht mehr herunter — sie liegen dann nur `
+ `noch auf dem Server.`
: `${n} MB gesetzt — greift sofort, kein Neustart noetig.`,
}));
} catch (err) {
clientWs.send(JSON.stringify({ type: "attachment_limit_info", error: err.message }));
}
}
// OpenClaw-Config-Handler entfernt — aria-core ist raus.
// ── Start ───────────────────────────────────────────────