feat: tool risk policy UI + wiring through all orchestrators
- New /settings/tools page: max_risk selector (low/medium/high) + per-tool override dropdowns (Default / Force include / Force exclude) for all 58 tools grouped by category with color-coded risk badges; JS updates Auto status live - get_tools_for_role() + get_openai_tools_for_role() now accept max_risk, whitelist, blacklist; _apply_risk_policy() handles the filtering logic - get_risk_policy() helper in auth_utils reads from tool_policy.json - Risk policy wired through orchestrator.py, openai_orchestrator.py, orchestrator_engine.py, nextcloud_talk.py, homeassistant.py - Tools nav link added to settings.html and notifications.html - CLAUDE.md and ARCH__SYSTEM.md updated: tool count 50→58, risk system docs, tool access control three-layer model documented Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,9 @@ async def run(
|
||||
tool_list: list[str] | None = None,
|
||||
confirm_allow: set[str] | None = None,
|
||||
confirm_deny: set[str] | None = None,
|
||||
max_risk: str | None = None,
|
||||
risk_whitelist: list[str] | None = None,
|
||||
risk_blacklist: list[str] | None = None,
|
||||
) -> OrchestratorResult:
|
||||
"""
|
||||
Run a tool-enabled task using an OpenAI-compatible API.
|
||||
@@ -73,7 +76,10 @@ async def run(
|
||||
_confirm_deny = frozenset(confirm_deny or ())
|
||||
effective_confirm = (CONFIRM_REQUIRED - set(_confirm_allow)) | set(_confirm_deny)
|
||||
|
||||
client, model_name, active_tools = _build_client(model_cfg, user_role, tool_list)
|
||||
client, model_name, active_tools = _build_client(
|
||||
model_cfg, user_role, tool_list,
|
||||
max_risk=max_risk, risk_whitelist=risk_whitelist, risk_blacklist=risk_blacklist,
|
||||
)
|
||||
tool_audit.set_context("openai", model_cfg.get("label") or model_name)
|
||||
|
||||
sys_content = (system_prompt or "") + _TOOL_INSTRUCTION
|
||||
@@ -420,6 +426,9 @@ def _build_client(
|
||||
model_cfg: dict | None,
|
||||
user_role: str = "user",
|
||||
tool_list: list[str] | None = None,
|
||||
max_risk: str | None = None,
|
||||
risk_whitelist: list[str] | None = None,
|
||||
risk_blacklist: list[str] | None = None,
|
||||
) -> tuple:
|
||||
"""Build AsyncOpenAI client and return (client, model_name, active_tools)."""
|
||||
if not model_cfg:
|
||||
@@ -439,7 +448,10 @@ def _build_client(
|
||||
if model_cfg.get("tools") is False:
|
||||
active_tools = []
|
||||
else:
|
||||
active_tools = get_openai_tools_for_role(user_role, tool_list)
|
||||
active_tools = get_openai_tools_for_role(
|
||||
user_role, tool_list,
|
||||
max_risk=max_risk, whitelist=risk_whitelist, blacklist=risk_blacklist,
|
||||
)
|
||||
return client, model_name, active_tools
|
||||
|
||||
|
||||
@@ -448,9 +460,15 @@ async def _execute_tool(
|
||||
arguments_json: str,
|
||||
user_role: str = "user",
|
||||
tool_list: list[str] | None = None,
|
||||
max_risk: str | None = None,
|
||||
risk_whitelist: list[str] | None = None,
|
||||
risk_blacklist: list[str] | None = None,
|
||||
) -> str:
|
||||
"""Parse tool arguments and execute with role-filtered callables."""
|
||||
_, callables = get_tools_for_role(user_role, tool_list)
|
||||
_, callables = get_tools_for_role(
|
||||
user_role, tool_list,
|
||||
max_risk=max_risk, whitelist=risk_whitelist, blacklist=risk_blacklist,
|
||||
)
|
||||
try:
|
||||
args = json.loads(arguments_json)
|
||||
except json.JSONDecodeError:
|
||||
|
||||
Reference in New Issue
Block a user