README / app.py
stackConsult's picture
Fix final indentation error on line 161 - remove leading spaces from audit_history_sample
46a1acf verified
Raw History Blame
6.05 kB
import gradio as gr
import sys
from typing import List, Dict, Any
# --- Consent/Event Audit Panel ---
def consent_audit_panel(consent_events: List[Dict[str, Any]]):
"""
UI Panel to show all consent events, opt-outs, and compliance flags per contact and batch.
Accepts a list of consent event dicts with structure as returned from backend JSON.
"""
audit_md = "# Consent/Event Audit\nPer-contact and batch consent history."
for event in consent_events:
audit_md += f"\n- Contact: {event.get('contact_id','?')} | Event: {event.get('event_type','?')} | Opt-out: {event.get('opt_out',False)} | Compliance: {event.get('compliance_flag','?')})"
return gr.Markdown(audit_md)
# --- Dynamic Branching Composer for Cadence Editing ---
def branching_composer(branches: List[Dict[str, Any]]):
"""
Visual sequence builder for editing cadences.
Structure assumed to be a list of dict branches with JSON mirroring backend.
"""
builder_md = "# Dynamic Cadence Branching\n" + "\n## Sequence Tree:"
for b in branches:
builder_md += f"\n- Step {b.get('step','?')}: {b.get('description','?')} (Next: {b.get('next','?')})"
return gr.Markdown(builder_md)
# --- Live Diagnostics Panel for Cadence Errors/Health ---
def diagnostics_panel(events: List[Dict[str, Any]]):
"""
Incident/event log UI widget to show errors and health of cadence system.
Format is a simple list of event dicts from backend state.
"""
diag_md = "# Live Diagnostics: Cadence Health\n"
for e in events:
diag_md += f"\n- [{e.get('timestamp','?')}] {e.get('type','?')}: {e.get('message','?')}{' [ERROR]' if e.get('level','').lower()=='error' else ''}"
return gr.Markdown(diag_md)
# --- Exportable Audit Trail Widget ---
def audit_trail_widget(audit_history: List[Dict[str, Any]]):
"""
Compliance and debug history view for export.
Accepts audit events from backend JSON/state.
"""
audit_log = 'Contact,Event,Opt-out,Compliance\n'
for item in audit_history:
audit_log += f"{item.get('contact_id','?')},{item.get('event_type','?')},{item.get('opt_out',False)},{item.get('compliance_flag','?')}\n"
return gr.Textbox(label="Audit Trail CSV", value=audit_log, lines=10)
# Example usage in Gradio Blocks
with gr.Blocks(title="StrategyStack UI") as demo:
gr.Markdown("# Outreach Cadence & Compliance Dashboard")
consent_events_sample = [
{
"contact_id": "LEAD_001",
"event_type": "consent_given",
"timestamp": "2025-11-06T06:20:00Z",
"opt_out": False,
"compliance_flag": "ok",
"region": "EU",
"method": "checkbox_onboarding_form",
"actor": "user",
"batch_id": "BATCH_Q4_2025_HEALTHCARE"
},
{
"contact_id": "LEAD_002",
"event_type": "opt_out",
"timestamp": "2025-11-06T06:21:00Z",
"opt_out": True,
"compliance_flag": "flagged",
"region": "US",
"method": "footer_unsubscribe",
"actor": "user",
"batch_id": "BATCH_Q4_2025_HEALTHCARE"
},
{
"contact_id": "LEAD_003",
"event_type": "consent_given",
"timestamp": "2025-11-06T07:15:00Z",
"opt_out": False,
"compliance_flag": "ok",
"region": "US",
"method": "api_integration",
"actor": "system",
"batch_id": "BATCH_Q4_2025_SAAS"
}
]
branches_sample = [
{
"step": 1,
"description": "Initial Welcome Email - Personalized Industry Context",
"channel": "email",
"timing": "immediate",
"next": 2,
"condition": "not_opted_out"
},
{
"step": 2,
"description": "LinkedIn Connection Request with Custom Note",
"channel": "linkedin",
"timing": "2_days_after_step_1",
"next": 3,
"condition": "no_reply_from_step_1"
},
{
"step": 3,
"description": "Follow-up Call - Pain Point Discovery",
"channel": "phone",
"timing": "3_days_after_step_2",
"next": 4,
"condition": "engagement_score_below_0.7"
},
{
"step": 4,
"description": "Case Study Email - Relevant to Industry",
"channel": "email",
"timing": "1_day_after_step_3",
"next": "END",
"condition": "not_connected"
}
]
diagnostics_sample = [
{
"timestamp": "2025-11-06T06:23:00Z",
"type": "info",
"message": "Cadence started for BATCH_Q4_2025_HEALTHCARE with 150 leads",
"level": "info",
"agent": "cadence_orchestrator"
},
{
"timestamp": "2025-11-06T06:29:00Z",
"type": "error",
"message": "Compliance block: Message suppressed for LEAD_002 - opted out via footer_unsubscribe",
"level": "error",
"agent": "compliance_agent"
},
{
"timestamp": "2025-11-06T06:33:00Z",
"type": "warning",
"message": "Rate limit reached for LinkedIn API; implementing exponential backoff for 15 minutes",
"level": "warning",
"agent": "outreach_agent"
},
{
"timestamp": "2025-11-06T06:45:00Z",
"type": "success",
"message": "Enrichment completed for 45 leads with intent_score > 0.8",
"level": "info",
"agent": "enrichment_agent"
},
{
"timestamp": "2025-11-06T07:00:00Z",
"type": "warning",
"message": "5 leads flagged for human validation due to incomplete firmographic data",
"level": "warning",
"agent": "validation_agent"
}
]
audit_history_sample = consent_events_sample