From 800a57d28a570c2eb9c41234b13ee4868830505c Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sat, 14 Mar 2026 17:22:56 +0100 Subject: [PATCH] fixed permission withour create new session, only restarted session --- diagnostic/index.html | 26 +++++++--- diagnostic/server.js | 108 ++++++++++++++++++++++++++++++++++++------ docker-compose.yml | 2 + 3 files changed, 116 insertions(+), 20 deletions(-) diff --git a/diagnostic/index.html b/diagnostic/index.html index a40ba44..9d89d55 100644 --- a/diagnostic/index.html +++ b/diagnostic/index.html @@ -584,7 +584,7 @@ if (msg.ok) { // Nachricht merken und nach Reload wieder anzeigen permsSavedMsg = (msg.info || 'Berechtigungen gespeichert!') - + '
Aenderungen werden erst bei einer neuen Session wirksam.' + + '
Session muss neu gestartet werden damit Aenderungen wirksam werden.' + ' '; 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 ──────────────────────────────── diff --git a/diagnostic/server.js b/diagnostic/server.js index e447a36..a892a59 100644 --- a/diagnostic/server.js +++ b/diagnostic/server.js @@ -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; } diff --git a/docker-compose.yml b/docker-compose.yml index ca04f85..c98e63c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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: