Sentinel / inspector.py
nihalaninihal's picture
Revamp Gradio app with Gradio 6, custom cybersecurity theme, and rich visualizations
f20603d
raw
history blame
5.83 kB
"""Enhanced environment inspector functions for Gradio Dataframe components."""
import pandas as pd
from sentinelops_arena.environment import SentinelOpsArena
def get_all_customers(env: SentinelOpsArena) -> pd.DataFrame:
"""Return all CRM customers as a DataFrame."""
rows = []
for cid, rec in env.crm.customers.items():
tier = rec.get("tier", "")
rows.append({
"customer_id": rec.get("customer_id", cid),
"name": rec.get("name", ""),
"tier": tier.value if hasattr(tier, "value") else str(tier),
"region": rec.get("region", ""),
"lifetime_value": rec.get("lifetime_value", 0.0),
})
if not rows:
return pd.DataFrame(columns=["customer_id", "name", "tier", "region", "lifetime_value"])
return pd.DataFrame(rows)
def get_all_invoices(env: SentinelOpsArena) -> pd.DataFrame:
"""Return all billing invoices as a DataFrame."""
rows = []
for iid, rec in env.billing.invoices.items():
status = rec.get("status", "")
rows.append({
"invoice_id": rec.get("invoice_id", iid),
"customer_id": rec.get("customer_id", ""),
"amount": rec.get("amount", 0.0),
"status": status.value if hasattr(status, "value") else str(status),
})
if not rows:
return pd.DataFrame(columns=["invoice_id", "customer_id", "amount", "status"])
return pd.DataFrame(rows)
def get_all_tickets(env: SentinelOpsArena) -> pd.DataFrame:
"""Return all ticketing system tickets as a DataFrame."""
rows = []
for tid, rec in env.ticketing.tickets.items():
priority = rec.get("priority", "")
status = rec.get("status", "")
rows.append({
"ticket_id": rec.get("ticket_id", tid),
"customer_id": rec.get("customer_id", ""),
"subject": rec.get("subject", ""),
"priority": priority.value if hasattr(priority, "value") else str(priority),
"status": status.value if hasattr(status, "value") else str(status),
"sla_deadline_tick": rec.get("sla_deadline_tick", 0),
})
if not rows:
return pd.DataFrame(columns=["ticket_id", "customer_id", "subject", "priority", "status", "sla_deadline_tick"])
return pd.DataFrame(rows)
def get_task_queue(env: SentinelOpsArena) -> pd.DataFrame:
"""Return the task queue as a DataFrame with truncated messages."""
rows = []
for task in env.tasks:
d = task.model_dump() if hasattr(task, "model_dump") else task
msg = str(d.get("message", ""))
task_type = d.get("task_type", "")
rows.append({
"task_id": d.get("task_id", ""),
"customer_id": d.get("customer_id", ""),
"task_type": task_type.value if hasattr(task_type, "value") else str(task_type),
"message": msg[:60] + ("..." if len(msg) > 60 else ""),
"arrival_tick": d.get("arrival_tick", 0),
})
if not rows:
return pd.DataFrame(columns=["task_id", "customer_id", "task_type", "message", "arrival_tick"])
return pd.DataFrame(rows)
def get_env_config_html(env: SentinelOpsArena) -> str:
"""Return styled HTML showing environment configuration."""
refund = env.billing.refund_policy.model_dump()
sla = env.ticketing.sla_rules.model_dump()
css = (
"font-family: 'Courier New', monospace;"
"background: #0d1117;"
"color: #c9d1d9;"
"padding: 20px;"
"border-radius: 10px;"
"border: 1px solid #30363d;"
)
heading_css = (
"color: #39ff14;"
"font-size: 14px;"
"font-weight: bold;"
"margin: 16px 0 8px 0;"
"text-transform: uppercase;"
"letter-spacing: 1.5px;"
)
table_css = (
"width: 100%;"
"border-collapse: collapse;"
"margin-bottom: 12px;"
)
th_css = (
"text-align: left;"
"padding: 6px 12px;"
"border-bottom: 1px solid #30363d;"
"color: #58a6ff;"
"font-size: 12px;"
)
td_css = (
"padding: 6px 12px;"
"border-bottom: 1px solid #21262d;"
"font-size: 13px;"
)
val_css = (
"color: #39ff14;"
"font-weight: bold;"
)
def row(key, value):
return (
f"<tr>"
f"<td style='{td_css}'>{key}</td>"
f"<td style='{td_css} {val_css}'>{value}</td>"
f"</tr>"
)
html = f"<div style='{css}'>"
# Environment params
html += f"<div style='{heading_css}'>Environment Parameters</div>"
html += f"<table style='{table_css}'>"
html += f"<tr><th style='{th_css}'>Parameter</th><th style='{th_css}'>Value</th></tr>"
html += row("MAX_TICKS", env.MAX_TICKS)
html += row("NUM_CUSTOMERS", env.NUM_CUSTOMERS)
html += row("NUM_INVOICES", env.NUM_INVOICES)
html += row("NUM_TICKETS", env.NUM_TICKETS)
html += row("NUM_TASKS", env.NUM_TASKS)
html += "</table>"
# Refund policy
html += f"<div style='{heading_css}'>Refund Policy</div>"
html += f"<table style='{table_css}'>"
html += f"<tr><th style='{th_css}'>Rule</th><th style='{th_css}'>Value</th></tr>"
html += row("Window (ticks)", refund["window_ticks"])
html += row("Requires Approval", refund["requires_approval"])
html += row("Max Amount", f"${refund['max_amount']:,.2f}")
html += "</table>"
# SLA rules
html += f"<div style='{heading_css}'>SLA Rules (ticks to resolve)</div>"
html += f"<table style='{table_css}'>"
html += f"<tr><th style='{th_css}'>Priority</th><th style='{th_css}'>Deadline (ticks)</th></tr>"
html += row("High", sla["high"])
html += row("Medium", sla["medium"])
html += row("Low", sla["low"])
html += "</table>"
html += "</div>"
return html