fixed permission withour create new session, only restarted session

This commit is contained in:
2026-03-14 17:22:56 +01:00
parent c23e4ff1ad
commit 800a57d28a
3 changed files with 116 additions and 20 deletions
+20 -6
View File
@@ -584,7 +584,7 @@
if (msg.ok) {
// Nachricht merken und nach Reload wieder anzeigen
permsSavedMsg = (msg.info || 'Berechtigungen gespeichert!')
+ '<br><span style="color:#FFD60A;font-size:10px;">Aenderungen werden erst bei einer neuen Session wirksam.</span>'
+ '<br><span style="color:#FFD60A;font-size:10px;">Session muss neu gestartet werden damit Aenderungen wirksam werden.</span>'
+ ' <button class="btn secondary" onclick="restartAriaSession()" style="padding:2px 8px;font-size:10px;margin-left:4px;">Session neu starten</button>';
s.style.color = '#34C759';
s.innerHTML = permsSavedMsg;
@@ -595,6 +595,21 @@
}
return;
}
if (msg.type === 'session_restarted') {
const s = document.getElementById('perms-status');
s.style.display = 'block';
if (msg.status === 'restarting') {
s.style.color = '#FFD60A';
s.textContent = 'aria-core wird neu gestartet...';
} else if (msg.status === 'ok') {
s.style.color = '#34C759';
s.textContent = msg.info || 'Session neu gestartet!';
} else {
s.style.color = '#FF6B6B';
s.textContent = 'Restart fehlgeschlagen: ' + (msg.error || '?');
}
return;
}
if (msg.type === 'model_info') {
const el = document.getElementById('setting-model');
const st = document.getElementById('model-status');
@@ -1306,12 +1321,11 @@
}
function restartAriaSession() {
if (!confirm('Neue Session starten? Die aktuelle Session bleibt erhalten aber wird inaktiv.')) return;
const ts = Date.now().toString(36);
send({ action: 'create_session', sessionName: `aria-${ts}` });
if (!confirm('Aktive Session neu starten? Der Kontext bleibt erhalten, Permissions werden neu geladen.')) return;
send({ action: 'restart_session' });
const s = document.getElementById('perms-status');
s.style.color = '#34C759';
s.textContent = 'Neue Session wird gestartet...';
s.style.color = '#FFD60A';
s.textContent = 'Session wird neu gestartet...';
}
// ── Einstellungen: Model ────────────────────────────────
+94 -14
View File
@@ -983,6 +983,8 @@ wss.on("connection", (ws) => {
ws.send(JSON.stringify({ type: "active_session", sessionKey: activeSessionKey }));
} else if (msg.action === "create_session") {
handleCreateSession(ws, msg.sessionName);
} else if (msg.action === "restart_session") {
handleRestartSession(ws);
} else if (msg.action === "list_brain") {
handleListBrain(ws);
} else if (msg.action === "read_brain_file") {
@@ -1314,6 +1316,56 @@ async function handleCreateSession(clientWs, sessionName) {
}
}
// ── Session neu starten (Container Restart) ────────────
async function handleRestartSession(clientWs) {
try {
log("info", "server", "Starte aria-core Container neu (Session Restart)...");
clientWs.send(JSON.stringify({ type: "session_restarted", status: "restarting" }));
// Container neu starten via Docker API
const http = require("http");
await new Promise((resolve, reject) => {
const req = http.request({
socketPath: "/var/run/docker.sock",
path: "/containers/aria-core/restart?t=5",
method: "POST",
}, (res) => {
let body = "";
res.on("data", d => body += d);
res.on("end", () => {
if (res.statusCode === 204 || res.statusCode === 200) resolve();
else reject(new Error(`Restart fehlgeschlagen: HTTP ${res.statusCode} ${body}`));
});
});
req.on("error", reject);
req.end();
});
log("info", "server", "aria-core Container neu gestartet");
// Warten bis Gateway wieder erreichbar (max 30s)
for (let i = 0; i < 15; i++) {
await new Promise(r => setTimeout(r, 2000));
try {
await dockerExec("aria-core", "echo ok");
log("info", "server", "aria-core ist wieder erreichbar");
clientWs.send(JSON.stringify({
type: "session_restarted", status: "ok",
info: "aria-core neu gestartet — Permissions werden bei der naechsten Nachricht geladen",
}));
// Aktive Session beibehalten
for (const c of browserClients) {
c.send(JSON.stringify({ type: "active_session", sessionKey: activeSessionKey }));
}
return;
} catch {}
}
clientWs.send(JSON.stringify({ type: "session_restarted", status: "timeout", error: "aria-core antwortet nicht nach 30s" }));
} catch (err) {
log("error", "server", `Session Restart fehlgeschlagen: ${err.message}`);
clientWs.send(JSON.stringify({ type: "session_restarted", status: "error", error: err.message }));
}
}
// ── Brain Viewer ────────────────────────────────────────
async function handleListBrain(clientWs) {
@@ -1401,6 +1453,8 @@ const OPENCLAW_SETTINGS_PATHS = [
"/home/node/.openclaw/settings.json",
"/home/node/.openclaw/agents/main/agent/settings.json",
"/home/node/.openclaw/config.json",
"/home/node/.claude/settings.json", // Claude Code User-Level
"/home/node/.openclaw/workspace/.claude/settings.json", // Claude Code Projekt-Level
];
async function findSettingsFile() {
@@ -1479,41 +1533,67 @@ async function handleSavePermissions(clientWs, allowedTools) {
try {
log("info", "server", `Speichere ${allowedTools.length} Tool-Berechtigungen in alle Settings-Pfade`);
// Bestehende Settings lesen und mergen
// Schreiben in ALLE moeglichen Pfade damit OpenClaw es sicher findet
// In ALLE moeglichen Pfade schreiben, in BEIDEN Formaten:
// 1. allowedTools: ["Bash", "Read", ...] — OpenClaw Format
// 2. permissions.allow: ["Bash(*)", "Read(*)", ...] — Claude Code Format
const script = [
'const fs=require("fs");const path=require("path");',
`const paths=${JSON.stringify(OPENCLAW_SETTINGS_PATHS)};`,
`const tools=${JSON.stringify(allowedTools)};`,
// Claude Code Format: Tool-Namen mit (*) Glob-Pattern
'const ccAllow=tools.map(t=>t+"(*)");',
'for(const f of paths){',
'let s={};try{s=JSON.parse(fs.readFileSync(f,"utf8"));}catch(e){}',
// OpenClaw Format
's.allowedTools=tools;',
// Claude Code Format
'if(!s.permissions)s.permissions={};',
's.permissions.allow=ccAllow;',
's.permissions.deny=[];',
'const dir=path.dirname(f);',
'try{fs.mkdirSync(dir,{recursive:true});}catch(e){}',
'fs.writeFileSync(f,JSON.stringify(s,null,2));',
'}',
// Verify: ersten Pfad zuruecklesen
`const v=JSON.parse(fs.readFileSync(paths[0],"utf8"));`,
'process.stdout.write(JSON.stringify(v.allowedTools||[]));',
// Verify: alle Pfade zuruecklesen
'const result={};',
'for(const f of paths){',
'try{const d=JSON.parse(fs.readFileSync(f,"utf8"));',
'result[f]={allowedTools:d.allowedTools||[],permsAllow:d.permissions&&d.permissions.allow||[]};}',
'catch(e){result[f]={error:e.message};}',
'}',
'process.stdout.write(JSON.stringify(result));',
].join("");
const b64 = Buffer.from(script).toString("base64");
const verifyRaw = await dockerExec("aria-core", `echo ${b64} | base64 -d | node`);
// Verify: gespeicherte Daten mit gewuenschten vergleichen
// Verify: gespeicherte Daten pruefen
let verifyResult = {};
let verified = false;
let savedTools = [];
let verifyDetails = [];
try {
savedTools = JSON.parse(verifyRaw.trim());
verified = Array.isArray(savedTools)
&& savedTools.length === allowedTools.length
&& allowedTools.every(t => savedTools.includes(t));
} catch {}
verifyResult = JSON.parse(verifyRaw.trim());
verified = true;
for (const [fpath, data] of Object.entries(verifyResult)) {
if (data.error) {
verifyDetails.push(`${fpath}: FEHLER ${data.error}`);
verified = false;
} else {
const ok = data.allowedTools.length === allowedTools.length
&& allowedTools.every(t => data.allowedTools.includes(t));
const ccOk = data.permsAllow.length === allowedTools.length;
verifyDetails.push(`${fpath}: allowedTools=${ok?"OK":"FEHLER"} permissions.allow=${ccOk?"OK":"FEHLER"} (${data.allowedTools.length}/${data.permsAllow.length} Tools)`);
if (!ok) verified = false;
}
}
} catch (e) {
verifyDetails.push(`Parse-Fehler: ${e.message}`);
}
log("info", "server", `Verify:\n${verifyDetails.join("\n")}`);
if (!verified) {
log("error", "server", `Verify fehlgeschlagen! Erwartet: ${JSON.stringify(allowedTools)}, Gelesen: ${verifyRaw}`);
clientWs.send(JSON.stringify({
type: "permissions_saved", ok: false,
error: `Verify fehlgeschlagen — Datei wurde nicht korrekt geschrieben. Erwartet ${allowedTools.length} Tools, gelesen: ${savedTools.length}`,
error: `Verify fehlgeschlagen:\n${verifyDetails.join("\n")}`,
}));
return;
}
+2
View File
@@ -47,6 +47,7 @@ services:
- ./aria-data/config/BOOTSTRAP.md:/home/node/.openclaw/workspace/BOOTSTRAP.md
- ./aria-data/config/BOOTSTRAP.md:/home/node/.openclaw/workspace/CLAUDE.md
- ./aria-data/config/openclaw.env:/home/node/.openclaw/workspace/.env
- claude-config:/home/node/.claude # Claude Code Settings (Permissions)
- ./aria-data/ssh:/home/node/.ssh # SSH Keys fuer VM-Zugriff
- /tmp/.X11-unix:/tmp/.X11-unix
- /var/run/docker.sock:/var/run/docker.sock # VM von innen verwalten
@@ -100,6 +101,7 @@ services:
volumes:
openclaw-config: # Persistiert ~/.openclaw (Model, Auth, Sessions)
claude-config: # Persistiert ~/.claude (Permissions, Settings)
networks:
aria-net: