chore: OpenClaw-Reste raus — tools/, docs/tool-permissions, Diagnostic-Permissions-Section
tools/export-jsonl-to-md.js
CLI-Konverter fuer OpenClaw-Session-JSONL zu Markdown. Mit OpenClaw raus.
tools/-Ordner ist jetzt leer und auch entfernt.
aria-data/docs/tool-permissions.md
Geschichts-Dokument zum OpenClaw-Tool-Permission-Bug. Nicht mehr relevant —
Brain hat eigenes Tool-Use-System (Skills + Meta-Tools), keine granulare
Permission-Maske. aria-data/docs/ Ordner war leer, mit raus.
diagnostic/index.html
- "Tool-Berechtigungen"-Section aus den Einstellungen raus. War nur ein
disabled Info-Toggle aus OpenClaw-Zeit ("Claude darf alle Tools").
Brain weiss zur Laufzeit selbst welche Tools es hat (META_TOOLS +
pro aktivem Skill ein dynamisches run_<skill>).
- .perm-grid / .perm-item / .perm-info CSS-Klassen entfernt (sonst nirgends
referenziert).
issue.md
- tools/export-jsonl-to-md.js-Eintrag mit "(mit OpenClaw raus)" markiert.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,137 +0,0 @@
|
||||
# OpenClaw Tool-Permissions — Stand 2026-03-15
|
||||
|
||||
## Das Problem (GELÖST)
|
||||
|
||||
ARIA hat ZWEI Tool-Systeme gleichzeitig: Claude Code Tools UND OpenClaw-native Tools.
|
||||
Das Model hat aber nur Zugriff auf **Claude Code Tools** (über den Proxy), nicht auf OpenClaw-native Tools.
|
||||
|
||||
### Root Cause: DREI Probleme gleichzeitig
|
||||
|
||||
```
|
||||
OpenClaw (aria-core) → API Request → claude-max-api-proxy (aria-proxy) → Claude Code CLI (--print Mode)
|
||||
↓
|
||||
Tools: WebFetch, Bash, etc. (Claude Code)
|
||||
NICHT: web_fetch, exec (OpenClaw-nativ)
|
||||
```
|
||||
|
||||
**Problem 1: Proxy benutzt `--print` Modus**
|
||||
- `claude-max-api-proxy` ruft Claude Code CLI mit `--print --output-format stream-json` auf
|
||||
- Der Prompt wird als einziger String übergeben, keine Tool-Definitionen von OpenClaw
|
||||
- Das Model sieht NUR Claude Code's eingebaute Tools (WebFetch, Bash, etc.)
|
||||
- OpenClaw-native Tools (web_fetch, exec) existieren NUR auf Gateway-Ebene, kommen nie beim Model an
|
||||
|
||||
**Problem 2: BOOTSTRAP.md hat die falschen Tools angewiesen**
|
||||
- BOOTSTRAP.md sagte: "NIEMALS WebFetch benutzen, stattdessen web_fetch"
|
||||
- Aber web_fetch existiert nicht im Claude Code CLI Kontext
|
||||
- Und WebFetch war das einzige Tool das funktioniert hätte
|
||||
- → Model hatte keine Tools die es benutzen "durfte"
|
||||
|
||||
**Problem 3: settings.json im Proxy war leer**
|
||||
- `/root/.claude/settings.json` enthielt nur `{}` (keine Permissions)
|
||||
- Claude Code CLI im headless-Modus kann keine Tool-Genehmigungen erteilen
|
||||
- → Selbst wenn das Model WebFetch benutzen wollte, war es nicht vorab genehmigt
|
||||
|
||||
## Die Lösung
|
||||
|
||||
### Fix 1: BOOTSTRAP.md + AGENT.md umgeschrieben
|
||||
|
||||
**Vorher (FALSCH):**
|
||||
- "NIEMALS WebFetch benutzen — hat Permission-Probleme"
|
||||
- "Benutze web_fetch (OpenClaw-nativ)"
|
||||
|
||||
**Nachher (KORREKT):**
|
||||
- "WebFetch — URLs abrufen, Webseiten lesen, APIs aufrufen, Wetter abfragen"
|
||||
- "Bash — Shell-Befehle ausfuehren (curl, ssh, docker, etc.)"
|
||||
- "Niemals sagen 'ich habe keinen Zugriff' — du hast Zugriff auf alles"
|
||||
|
||||
### Fix 2: `CLAUDE_CODE_BUBBLEWRAP=1` + `--dangerously-skip-permissions`
|
||||
|
||||
**Der Schlüssel-Fix.** Zwei Zeilen in `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
# 1. sed-Patch: --dangerously-skip-permissions in manager.js einfügen
|
||||
sed -i 's/"--no-session-persistence",/"--no-session-persistence","--dangerously-skip-permissions",/' $$DIST/subprocess/manager.js &&
|
||||
|
||||
# 2. Environment-Variable: Root-Check umgehen
|
||||
environment:
|
||||
- CLAUDE_CODE_BUBBLEWRAP=1
|
||||
```
|
||||
|
||||
**Warum beides nötig:**
|
||||
- `--dangerously-skip-permissions` umgeht alle Tool-Permission-Checks in Claude Code CLI
|
||||
- Aber: Claude Code CLI blockiert dieses Flag wenn es als root läuft
|
||||
- `CLAUDE_CODE_BUBBLEWRAP=1` überspringt den Root-Check (gefunden im minifizierten `cli.js`)
|
||||
- Proxy-Container (`node:22-alpine`) läuft als root → ohne BUBBLEWRAP geht's nicht
|
||||
|
||||
**Resultierende CLI-Argumente:**
|
||||
```
|
||||
claude --print --output-format stream-json --verbose --include-partial-messages \
|
||||
--model opus --no-session-persistence --dangerously-skip-permissions "prompt"
|
||||
```
|
||||
|
||||
## Wie der Proxy intern funktioniert
|
||||
|
||||
```
|
||||
openai-to-cli.js: OpenAI Messages → einzelner Prompt-String
|
||||
system → <system>...</system>
|
||||
user → direkt
|
||||
assistant → <previous_response>...</previous_response>
|
||||
|
||||
subprocess/manager.js: Spawnt `claude --print ... --dangerously-skip-permissions "{prompt}"`
|
||||
|
||||
cli-to-openai.js: Claude CLI JSON-Stream → OpenAI Chat Completion Chunks
|
||||
```
|
||||
|
||||
Der Proxy leitet KEINE Tool-Definitionen von OpenClaw weiter.
|
||||
Tool-Calls passieren INTERN in der Claude Code CLI und sind für OpenClaw transparent.
|
||||
|
||||
## Permission-Architektur
|
||||
|
||||
**Granulare Tool-Kontrolle ist NICHT möglich.** Es ist Alles-oder-Nichts:
|
||||
- `--dangerously-skip-permissions` AN → ARIA kann alle Claude Code Tools benutzen
|
||||
- `--dangerously-skip-permissions` AUS → ARIA kann keine Tools benutzen
|
||||
|
||||
OpenClaw's eigene Permissions (`tools.allow/deny` in `openclaw.json`) haben **keinen Effekt** auf die
|
||||
Claude Code Tools — die laufen komplett auf Proxy-Seite.
|
||||
|
||||
## Was NICHT funktioniert hat (17 Versuche)
|
||||
|
||||
1. **settings.json in aria-core** — OpenClaw benutzt NICHT Claude Code's settings.json
|
||||
2. **tools.allow mit PascalCase** (WebFetch, Grep) — OpenClaw kennt diese Namen nicht
|
||||
3. **tools.allow mit snake_case** (web_fetch) — Nur exec, read, write, edit erkannt
|
||||
4. **tools.allow mit Wildcard** `["*"]` — Hat nicht geholfen
|
||||
5. **tools.allow leer + tools.profile: "full"** — Nur ohne andere Fehler
|
||||
6. **System-Prompt Anweisung allein** — Reicht nicht wenn Tools blockiert sind
|
||||
7. **exec-approvals Wildcard allein** — Reicht nicht bei Config-Validation-Error
|
||||
8. **`openclaw config unset tools.exec.ask`** — CLI kennt den Pfad nicht
|
||||
9. **BOOTSTRAP.md mit OpenClaw-Tool-Namen** — Tools existieren nur auf Gateway-Ebene
|
||||
10. **settings.json im Proxy ohne BOOTSTRAP.md Fix** — BOOTSTRAP.md verbot die Tools
|
||||
11. **tools.byProvider.proxy.profile full** — Kein Effekt
|
||||
12. **settings.json + BOOTSTRAP.md ohne --dangerously-skip-permissions** — `--print` ignoriert settings.json
|
||||
13. **Manuelles `docker exec sed`** — Wird bei jedem Restart überschrieben
|
||||
14. **`--dangerously-skip-permissions` ohne BUBBLEWRAP** — Root-Check blockiert
|
||||
15. **`--allowedTools`** — Variadisches Argument frisst den Prompt
|
||||
16. **`--permission-mode bypassPermissions`** — Gleicher Root-Check
|
||||
17. **Non-Root User (`su node`)** — Auth-Pfad-Probleme, Credentials unerreichbar
|
||||
|
||||
## Wichtige Pfade
|
||||
|
||||
### aria-core (OpenClaw)
|
||||
- `/home/node/.openclaw/openclaw.json` — OpenClaw Haupt-Config
|
||||
- `/home/node/.openclaw/exec-approvals.json` — Exec Approvals
|
||||
- `/tmp/openclaw/openclaw-YYYY-MM-DD.log` — Tages-Log
|
||||
|
||||
### aria-proxy (Claude Code CLI)
|
||||
- `/root/.claude/.credentials.json` — Auth Credentials (NICHT in /root/.config/claude/)
|
||||
- `/usr/local/lib/node_modules/claude-max-api-proxy/dist/` — Proxy Source
|
||||
- `/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js` — Claude Code CLI (enthält Root-Check)
|
||||
|
||||
## OpenClaw CLI Referenz
|
||||
|
||||
```bash
|
||||
openclaw config get/set/unset <path> # Config verwalten
|
||||
openclaw approvals get # Exec-Approvals anzeigen
|
||||
openclaw approvals allowlist add # Exec-Pattern freigeben
|
||||
openclaw doctor [--fix] # Health Check
|
||||
openclaw gateway status # Gateway-Status
|
||||
```
|
||||
+3
-27
@@ -120,12 +120,6 @@
|
||||
/* Settings */
|
||||
.settings-section { margin-bottom:20px; }
|
||||
.settings-section h2 { margin-bottom:12px; }
|
||||
.perm-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(220px, 1fr)); gap:8px; }
|
||||
.perm-item { display:flex; align-items:center; justify-content:space-between; background:#12122A;
|
||||
border:1px solid #1E1E2E; border-radius:6px; padding:8px 12px; }
|
||||
.perm-item .perm-info { flex:1; min-width:0; }
|
||||
.perm-item .perm-name { font-size:13px; color:#E0E0F0; font-weight:bold; }
|
||||
.perm-item .perm-desc { font-size:10px; color:#8888AA; margin-top:2px; }
|
||||
.toggle { position:relative; width:40px; height:22px; flex-shrink:0; margin-left:8px; }
|
||||
.toggle input { opacity:0; width:0; height:0; }
|
||||
.toggle .slider { position:absolute; cursor:pointer; top:0; left:0; right:0; bottom:0;
|
||||
@@ -661,27 +655,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tool-Berechtigungen -->
|
||||
<div class="settings-section">
|
||||
<h2>Tool-Berechtigungen</h2>
|
||||
<div style="font-size:11px;color:#8888AA;margin-bottom:12px;">
|
||||
Claude Code laeuft mit <code>--dangerously-skip-permissions</code> im Proxy — Alles oder Nichts.
|
||||
Granulare Tool-Kontrolle ist in dieser Architektur nicht moeglich.
|
||||
</div>
|
||||
<div class="card" style="max-width:500px;">
|
||||
<div class="perm-item" style="border:none;padding:0;">
|
||||
<div class="perm-info">
|
||||
<div class="perm-name">Claude darf alle Tools benutzen</div>
|
||||
<div class="perm-desc">WebFetch, Bash, Read/Write/Edit, WebSearch, Agent, etc.</div>
|
||||
</div>
|
||||
<label class="toggle"><input type="checkbox" checked disabled><span class="slider"></span></label>
|
||||
</div>
|
||||
<div style="font-size:10px;color:#555570;margin-top:8px;">
|
||||
Deaktivieren = <code>--dangerously-skip-permissions</code> aus docker-compose.yml entfernen.
|
||||
Dann kann ARIA keine Tools mehr benutzen (auch kein WebFetch fuer Wetter etc.).
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Tool-Berechtigungen-Section entfernt — Brain steuert Tool-Use
|
||||
selbst (Skills + skill_create Meta-Tool). Es gibt keine granulare
|
||||
Permission-Maske, Brain weiss zur Laufzeit welche Tools es hat. -->
|
||||
|
||||
<!-- Model-Einstellungen -->
|
||||
<div class="settings-section">
|
||||
|
||||
@@ -149,7 +149,7 @@ Wichtige Mechanismen:
|
||||
- [x] Piper komplett entfernt
|
||||
- [x] Gespraechsmodus: Speech-Gate strenger (-28dB / 500ms)
|
||||
- [x] Diagnostic: Archivierte Session-Versionen (.reset.*) angezeigt + exportierbar
|
||||
- [x] tools/export-jsonl-to-md.js: CLI-Konverter fuer Session-JSONL zu Markdown
|
||||
- [x] tools/export-jsonl-to-md.js: CLI-Konverter fuer Session-JSONL zu Markdown (mit OpenClaw raus)
|
||||
- [x] NO_REPLY-Filter in Bridge + Diagnostic
|
||||
- [x] Audio-Ducking + Exklusiv-Focus (Kotlin AudioFocusModule)
|
||||
- [x] TTS-Cleanup serverseitig: Code-Bloecke raus, Einheiten ausgeschrieben, Abkuerzungen buchstabiert, URLs zu "ein Link"
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Exportiert ein OpenClaw Session-JSONL (auch .reset.*) als Markdown.
|
||||
*
|
||||
* Nutzung:
|
||||
* node export-jsonl-to-md.js <input.jsonl> [output.md]
|
||||
*
|
||||
* Oder direkt aus dem aria-core Container:
|
||||
* docker exec aria-core cat /home/node/.openclaw/agents/main/sessions/<ID>.jsonl.reset.<TS> \
|
||||
* | node export-jsonl-to-md.js - > output.md
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
|
||||
const inputArg = process.argv[2];
|
||||
const outputArg = process.argv[3];
|
||||
|
||||
if (!inputArg) {
|
||||
console.error("Usage: export-jsonl-to-md.js <input.jsonl|-> [output.md]");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const raw = inputArg === "-" ? fs.readFileSync(0, "utf-8") : fs.readFileSync(inputArg, "utf-8");
|
||||
const lines = raw.split("\n").filter(l => l.trim());
|
||||
|
||||
const blocks = [];
|
||||
for (const line of lines) {
|
||||
let obj;
|
||||
try { obj = JSON.parse(line); } catch { continue; }
|
||||
if (obj.type !== "message" || !obj.message) continue;
|
||||
const role = obj.message.role;
|
||||
if (role !== "user" && role !== "assistant") continue;
|
||||
|
||||
let text = "";
|
||||
const content = obj.message.content;
|
||||
if (typeof content === "string") text = content;
|
||||
else if (Array.isArray(content)) text = content.filter(c => c.type === "text").map(c => c.text || "").join("\n");
|
||||
if (!text) continue;
|
||||
|
||||
if (role === "user") {
|
||||
text = text.replace(/^Sender \(untrusted metadata\):[\s\S]*?```[\s\S]*?```\s*\n*/m, "").trim();
|
||||
text = text.replace(/^\[.*?\]\s*/, "").trim();
|
||||
} else {
|
||||
text = text.replace(/^\[\[reply_to_\w+\]\]\s*/g, "").trim();
|
||||
}
|
||||
if (!text) continue;
|
||||
|
||||
const ts = obj.message.timestamp || obj.timestamp || 0;
|
||||
const when = ts ? new Date(ts).toISOString().replace("T", " ").slice(0, 19) : "";
|
||||
const heading = role === "user" ? "## 🧑 User" : "## 🤖 ARIA";
|
||||
blocks.push(`${heading}${when ? ` — ${when}` : ""}\n\n${text}`);
|
||||
}
|
||||
|
||||
const exportedAt = new Date().toISOString().replace("T", " ").slice(0, 19);
|
||||
const title = inputArg === "-" ? "Session" : inputArg.split("/").pop().replace(/\.jsonl.*/, "");
|
||||
const md = [
|
||||
`# Session: ${title}`,
|
||||
``,
|
||||
`Exportiert: ${exportedAt} `,
|
||||
`Quelle: ${inputArg === "-" ? "stdin" : inputArg}`,
|
||||
`Nachrichten: ${blocks.length}`,
|
||||
``,
|
||||
`---`,
|
||||
``,
|
||||
blocks.join("\n\n---\n\n"),
|
||||
``,
|
||||
].join("\n");
|
||||
|
||||
if (outputArg) {
|
||||
fs.writeFileSync(outputArg, md);
|
||||
console.error(`OK: ${blocks.length} Nachrichten → ${outputArg}`);
|
||||
} else {
|
||||
process.stdout.write(md);
|
||||
}
|
||||
Reference in New Issue
Block a user