"""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: 'IBM Plex Mono', monospace;" "background: var(--sentinel-surface);" "color: var(--sentinel-text);" "padding: 20px;" "border-radius: 8px;" "border: 1px solid var(--sentinel-border);" ) heading_css = ( "color: var(--sentinel-green);" "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 var(--sentinel-border);" "color: var(--sentinel-blue);" "font-size: 12px;" ) td_css = ( "padding: 6px 12px;" "border-bottom: 1px solid rgba(201, 209, 217, 0.1);" "font-size: 13px;" ) val_css = ( "color: var(--sentinel-green);" "font-weight: bold;" ) def row(key, value): return ( f"" f"{key}" f"{value}" f"" ) html = f"
" # Environment params html += f"
Environment Parameters
" html += f"" html += f"" 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 += "
ParameterValue
" # Refund policy html += f"
Refund Policy
" html += f"" html += f"" html += row("Window (ticks)", refund["window_ticks"]) html += row("Requires Approval", refund["requires_approval"]) html += row("Max Amount", f"${refund['max_amount']:,.2f}") html += "
RuleValue
" # SLA rules html += f"
SLA Rules (ticks to resolve)
" html += f"" html += f"" html += row("High", sla["high"]) html += row("Medium", sla["medium"]) html += row("Low", sla["low"]) html += "
PriorityDeadline (ticks)
" html += "
" return html