refactor(monitoring): N2 - tach monitoring_tab.py, CanonicalAuditLogger, MonitoringQueryService, go circular import, sandbox matrix
- ui/monitoring_tab.py (1546 dong) tach thanh presentation/monitoring/** (container + 7 tab/card + shared helper), ui/monitoring_tab.py con lai re-export shim de app.py khong doi. - infrastructure/telemetry/audit_logger.py: CanonicalAuditLogger, core/audit_log.py thanh wrapper mong, tuong thich nguoc 100% voi schema .jsonl cu. - application/monitoring/monitoring_query_service.py: MonitoringQueryService read-only, filter/sort/pagination, khong import PySide6. - Go circular import model_pricing<->usage_tracker va agent_security<-> agent_security_alert (core/agent_security_types.py moi). - infrastructure/sandbox/sandbox_capabilities.py: SandboxCapabilityMatrix theo OS (Windows/Linux/macOS), chua dau noi vao core/sandbox_manager.py. - conftest.py: sua loi checkout khong ten cowork_local khien pytest import nham thu muc khac. - 77 test moi, 167/167 pass. QA da xac nhan UI/business logic khong doi (xem evidence/report/unified_report.html). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
86c27e2e79
commit
40b12ecb15
@@ -0,0 +1,90 @@
|
||||
"""Badge/label vocabulary shared by the Monitoring event tables and detail
|
||||
panel — human labels for a raw audit ``name``, and the (QSS object name,
|
||||
i18n key) pair for the "Trạng thái"/"Mức độ" pills.
|
||||
|
||||
``apply_badge`` replaces the two byte-identical
|
||||
``_EventDetailPanel._apply_badge`` / ``MonitoringTab._set_badge`` static
|
||||
methods the original file duplicated.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Tuple
|
||||
|
||||
from PySide6.QtWidgets import QLabel
|
||||
|
||||
from ....i18n import tr
|
||||
|
||||
# Human label for the raw ``name`` an audit event is recorded under — the
|
||||
# "Loại" field in the detail panel. Anything not in this map (custom tool
|
||||
# names, etc.) just shows its raw name, same as the table's Hành động column.
|
||||
_ACTION_LABEL_KEYS = {
|
||||
"prompt": "monitoring.action_prompt",
|
||||
"dangerous_command": "monitoring.action_dangerous_command",
|
||||
"run_command": "monitoring.action_dangerous_command",
|
||||
"install_package": "monitoring.action_install_package",
|
||||
"path_outside_sandbox": "monitoring.action_path_outside_sandbox",
|
||||
"network_blocked": "monitoring.action_network_blocked",
|
||||
"secret_in_output": "monitoring.action_secret_in_output",
|
||||
}
|
||||
|
||||
|
||||
def action_label(name: str) -> str:
|
||||
key = _ACTION_LABEL_KEYS.get(name)
|
||||
return tr(key) if key else name
|
||||
|
||||
|
||||
# (badge QSS object name, i18n key) for the "Trạng thái" pill, mapped onto
|
||||
# the app's existing badge* tones (theme.py).
|
||||
_STATUS_INFO = {
|
||||
"path_outside_sandbox": ("badgeSuccess", "monitoring.status_path"),
|
||||
"network_blocked": ("badge", "monitoring.status_network"),
|
||||
"secret_in_output": ("badgeWarn", "monitoring.status_secret"),
|
||||
}
|
||||
_STATUS_DEFAULT = ("badgePurple", "monitoring.status_blocked")
|
||||
|
||||
|
||||
def status_info(name: str, kind: str = "security_block", ok: bool = False) -> Tuple[str, str]:
|
||||
if name in _STATUS_INFO:
|
||||
return _STATUS_INFO[name]
|
||||
if kind == "security_block":
|
||||
# Security Events rows are always ok=False — an unmapped name here
|
||||
# still means "blocked by some rule", never a plain failure.
|
||||
return _STATUS_DEFAULT
|
||||
# MCP calls / generic Action Logs rows: no fixed enforcement-rule
|
||||
# vocabulary applies, so fall back to the event's own ok/fail outcome.
|
||||
return ("badgeSuccess", "monitoring.status_ok") if ok else ("badgeDanger", "monitoring.status_failed")
|
||||
|
||||
|
||||
def severity_info(name: str, kind: str = "security_block", ok: bool = False) -> Tuple[str, str]:
|
||||
# An unapproved shell command is the one CRITICAL case; everything else
|
||||
# blocked is MEDIUM.
|
||||
if name in ("dangerous_command", "run_command"):
|
||||
return "badgeDanger", "monitoring.severity_critical"
|
||||
if kind == "security_block":
|
||||
return "badgeWarn", "monitoring.severity_medium"
|
||||
# A successful MCP call / action is routine (INFO); a failed one still
|
||||
# deserves the same MEDIUM tone Security Events uses for a blocked rule.
|
||||
return ("badge", "monitoring.severity_info") if ok else ("badgeWarn", "monitoring.severity_medium")
|
||||
|
||||
|
||||
def agent_badge_name(name: str) -> str:
|
||||
"""Badge tone for the Agent field's pill — the same identity-colour
|
||||
mapping ``formatters.agent_avatar_colour`` uses, expressed as one of the
|
||||
shared badge* QSS classes (theme.py) instead of a literal hex."""
|
||||
if "Security" in name:
|
||||
return "badgeDanger"
|
||||
if "Cowork" in name:
|
||||
return "badge"
|
||||
if name == "schedule":
|
||||
return "badgeWarn"
|
||||
if name == "graphrag":
|
||||
return "badgePurple"
|
||||
if "Code" in name:
|
||||
return "badgeSuccess"
|
||||
return "badge"
|
||||
|
||||
|
||||
def apply_badge(label: QLabel, object_name: str) -> None:
|
||||
label.setObjectName(object_name)
|
||||
label.style().unpolish(label)
|
||||
label.style().polish(label)
|
||||
Reference in New Issue
Block a user