feat(diagnostic): warnt, wenn der Proxy mit veralteten Patches laeuft

Der Proxy kopiert proxy-patches/*.js beim START ueber den npm-Code. Wer nach
einem git pull nur `restart` macht — oder neu startet, BEVOR der Pull durch ist
— laeuft still mit der alten Fassung weiter. Nichts deutet darauf hin: der
Container ist "Up", die Oberflaeche sieht normal aus, die Aenderung wirkt
einfach nicht.

Das hat heute zweimal Zeit gekostet: einmal wirkte ein Proxy-Fix nicht, einmal
blieb die Modell-Liste alt, obwohl der Code laengst gepullt war (Proxy
gestartet 08:51, Patches gepullt 09:28).

Die Einstellungen vergleichen jetzt die Zeitstempel der Quelldateien mit den
eingespielten und zeigen einen Hinweis samt fertigem Befehl — inklusive der
Angabe, welche Datei wann geaendert und wann eingespielt wurde. Toleranz 5s,
weil Quelle und Kopie beim Start kurz nacheinander entstehen. Ein Fehler beim
Pruefen loest bewusst KEINEN Alarm aus, sonst stuende dort eine Warnung, die
nichts ueber die Patches aussagt.

Dazu: der Datenschutz-Block sagt jetzt ausdruecklich, dass KEIN Neustart noetig
ist — die CLI liest ~/.claude/settings.json bei jedem Aufruf neu. Nur ein
gerade laufender Turn nutzt noch die alte Einstellung.

4 Pruefungen gegen den echten Container, in beide Richtungen: schweigt nach
frischem Start, erkennt eine veraltete Kopie samt Zeitstempeln, schweigt nach
Wiederherstellung.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-03 11:38:04 +02:00
co-authored by Claude Opus 5
parent 988b074478
commit e67659b78a
2 changed files with 92 additions and 2 deletions
+46
View File
@@ -3217,6 +3217,8 @@ wss.on("connection", (ws) => {
handleSetModel(ws, msg.model);
} else if (msg.action === "test_model") {
handleTestModel(ws, msg.model);
} else if (msg.action === "check_proxy_patches") {
handleCheckProxyPatches(ws);
} else if (msg.action === "get_privacy_flags") {
handleGetPrivacyFlags(ws);
} else if (msg.action === "set_privacy_flags") {
@@ -3647,6 +3649,50 @@ function handleSetModel(clientWs, model) {
return;
}
// ── Laufen im Proxy die aktuellen Patches? ──────────────────────────
//
// Der Proxy kopiert proxy-patches/*.js beim START ueber den npm-Code (siehe
// docker-compose.yml, command:). Wer nach einem git pull nur `restart` macht —
// oder neu startet, BEVOR der Pull durch ist — laeuft still mit der alten
// Fassung weiter. Das faellt sonst nirgends auf: der Container ist "Up", die
// Oberflaeche sieht normal aus, nur wirkt die Aenderung nicht.
//
// Darum: Zeitstempel der Quelldateien gegen die eingespielten vergleichen.
const PROXY_PATCH_MAP = [
["routes.js", "server/routes.js"],
["manager.js", "subprocess/manager.js"],
["openai-to-cli.js", "adapter/openai-to-cli.js"],
["cli-to-openai.js", "adapter/cli-to-openai.js"],
];
async function handleCheckProxyPatches(clientWs) {
try {
const dist = "/usr/local/lib/node_modules/claude-max-api-proxy/dist";
const pairs = PROXY_PATCH_MAP
.map(([src, dst]) => `/proxy-patches/${src} ${dist}/${dst}`).join(" ");
// %Y = mtime als Unix-Zeit, %n = Dateiname
const out = await dockerExec("aria-proxy", `stat -c '%Y %n' ${pairs} 2>/dev/null || true`);
const mtime = {};
for (const line of String(out || "").split("\n")) {
const m = line.trim().match(/^(\d+)\s+(.+)$/);
if (m) mtime[m[2]] = parseInt(m[1], 10);
}
const stale = [];
for (const [src, dst] of PROXY_PATCH_MAP) {
const a = mtime[`/proxy-patches/${src}`];
const b = mtime[`${dist}/${dst}`];
if (a == null || b == null) continue;
// Toleranz 5s: Quelle und Kopie entstehen beim Start kurz nacheinander.
if (a > b + 5) stale.push({ file: src, srcAt: a * 1000, activeAt: b * 1000 });
}
clientWs.send(JSON.stringify({ type: "proxy_patch_state", stale }));
} catch (err) {
// Kein Alarm bei einem Pruef-Fehler — sonst steht da eine Warnung, die
// gar nichts ueber die Patches aussagt.
clientWs.send(JSON.stringify({ type: "proxy_patch_state", stale: [], error: String((err && err.message) || err) }));
}
}
// ── Einstellungen: Datenschutz-Schalter von Claude Code ─────────────
//
// Drei Kanaele, ueber die Claude Code von sich aus Daten an Anthropic bzw. an