feat: role-based tool access, confirmation gates, and new orchestrator tools
- auth_utils: get_user_role() reads role from auth.json (admin|user, default user) - manage_passwords: new `role` command to promote/demote users (admin-only by convention) - tools/__init__: TOOL_ROLES map, CONFIRM_REQUIRED set, get_tools_for_role(), get_openai_tools_for_role() — both orchestrators now filter tools by caller's role - tools/system: cortex_restart (detached subprocess, 5s delay), cortex_logs (admin-only) - tools/web: http_fetch — direct URL fetch, distinct from web_search - tools/files: file_list (directory listing), file_write (restricted paths, admin-only) - tools/notify: nc_talk_send — proactive outbound via notification.py - orchestrator_engine + openai_orchestrator: user_role param; CONFIRM_REQUIRED tools return a confirmation-request result instead of executing — loop breaks after Claude asks user to confirm in a follow-up message - home/scott/auth.json: role set to admin Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,7 @@ from datetime import datetime, timezone
|
||||
from fastapi import APIRouter
|
||||
from pydantic import BaseModel
|
||||
|
||||
from auth_utils import get_user_gemini_key
|
||||
from auth_utils import get_user_gemini_key, get_user_role
|
||||
from config import settings
|
||||
from context_loader import load_context
|
||||
from persona import set_context, validate as validate_persona
|
||||
@@ -163,6 +163,8 @@ async def _run_job(job_id: str, req: OrchestrateRequest, user: str) -> None:
|
||||
# Choose engine based on the orchestrator role in the model registry
|
||||
orch_model = model_registry.get_model_for_role(user, "orchestrator")
|
||||
|
||||
user_role = get_user_role(user)
|
||||
|
||||
if orch_model and orch_model.get("type") == "local_openai":
|
||||
result = await openai_orchestrator.run(
|
||||
task=req.task,
|
||||
@@ -170,6 +172,7 @@ async def _run_job(job_id: str, req: OrchestrateRequest, user: str) -> None:
|
||||
session_messages=session_messages,
|
||||
model_cfg=orch_model,
|
||||
respond_with_final=req.respond_with_claude,
|
||||
user_role=user_role,
|
||||
)
|
||||
else:
|
||||
# Use the API key embedded in the resolved model config (V2 registry with
|
||||
@@ -186,6 +189,7 @@ async def _run_job(job_id: str, req: OrchestrateRequest, user: str) -> None:
|
||||
gemini_api_key=gemini_key,
|
||||
model_name=orch_model.get("model_name") if orch_model else None,
|
||||
response_role=req.chat_role,
|
||||
user_role=user_role,
|
||||
)
|
||||
|
||||
# Save the turn to the session store so it survives a page refresh
|
||||
|
||||
Reference in New Issue
Block a user