feat: run claude as non-root for bypassPermissions + replace MCP menu with live tools view
This commit is contained in:
parent
004b1efdc6
commit
318e7f01ad
1 changed files with 32 additions and 6 deletions
|
|
@ -231,6 +231,7 @@ class ClaudeProcessManager:
|
|||
self._broadcast_queues: List[asyncio.Queue] = []
|
||||
self._is_ready = False
|
||||
self._status = "not_started" # not_started, starting, ready, dead
|
||||
self._available_tools: List[dict] = [] # populated from system/init event
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
|
|
@ -249,17 +250,18 @@ class ClaudeProcessManager:
|
|||
self._status = "starting"
|
||||
logger.info("Starting Claude interactive process...")
|
||||
|
||||
# Run as non-root user so --permission-mode bypassPermissions is allowed
|
||||
# (Claude CLI refuses bypassPermissions when running as root)
|
||||
env = os.environ.copy()
|
||||
env["HOME"] = "/home/claudeuser"
|
||||
|
||||
# Build command: interactive claude with stream-json I/O
|
||||
# --permission-mode bypassPermissions allows the agent to use all tools
|
||||
# (Bash, file ops, MCP servers) without interactive confirmation prompts
|
||||
cmd = [
|
||||
"claude",
|
||||
"--output-format", "stream-json",
|
||||
"--input-format", "stream-json",
|
||||
"--verbose",
|
||||
"--permission-mode", "bypassPermissions",
|
||||
"su", "-s", "/bin/bash", "claudeuser", "-c",
|
||||
"claude --output-format stream-json --input-format stream-json "
|
||||
"--verbose --permission-mode bypassPermissions"
|
||||
]
|
||||
|
||||
try:
|
||||
|
|
@ -359,7 +361,8 @@ class ClaudeProcessManager:
|
|||
if event_type == "system" and event.get("subtype") == "init":
|
||||
self._current_session_id = event.get("session_id")
|
||||
self._is_ready = True
|
||||
logger.info(f"Claude session initialized: {self._current_session_id}")
|
||||
self._available_tools = event.get("tools", [])
|
||||
logger.info(f"Claude session initialized: {self._current_session_id}, tools: {len(self._available_tools)}")
|
||||
|
||||
elif event_type == "result":
|
||||
# End of a response turn
|
||||
|
|
@ -636,6 +639,29 @@ async def claude_status():
|
|||
}
|
||||
|
||||
|
||||
@app.get("/api/claude/tools")
|
||||
async def claude_tools():
|
||||
"""Return the tools available in the current Claude session (from system/init)."""
|
||||
tools = claude_mgr._available_tools
|
||||
# Group by MCP server prefix (e.g. "mcp__truenas__list_pools" -> "truenas")
|
||||
servers: dict = {}
|
||||
builtin = []
|
||||
for t in tools:
|
||||
name = t.get("name", "")
|
||||
if name.startswith("mcp__"):
|
||||
parts = name.split("__")
|
||||
server = parts[1] if len(parts) > 1 else "unknown"
|
||||
servers.setdefault(server, []).append(name)
|
||||
else:
|
||||
builtin.append(name)
|
||||
return {
|
||||
"total": len(tools),
|
||||
"mcp_servers": {k: len(v) for k, v in servers.items()},
|
||||
"builtin_tools": builtin,
|
||||
"raw": tools,
|
||||
}
|
||||
|
||||
|
||||
# -------- Chat --------
|
||||
|
||||
@app.get("/api/chat/sessions")
|
||||
|
|
|
|||
Reference in a new issue