"""Business-first presentation helpers for the Agent 9 Gradio demo.""" from __future__ import annotations import html from src.schemas import WorkflowRun PLAYBACK_DELAY_SECONDS = 0.20 NODE_LABELS = { "validate_intake": "Check household intake", "ai_intake_organizer": "AI Intake Organizer", "document_check": "Check onboarding documents", "policy_check": "Apply onboarding rules", "create_onboarding_package": "Prepare onboarding package", "verify_onboarding_package": "Verify onboarding package", "review_gate": "Choose review path", "onboarding_ready": "Standard package ready", "human_review": "Operations / compliance review", "reviewed_onboarding": "Ready after human review", } EVENT_LABELS = { "WORKFLOW_STARTED": "Workflow started", "NODE_STARTED": "Step started", "NODE_COMPLETED": "Step completed", "NODE_FAILED": "Step stopped safely", "NODE_SKIPPED": "Step not needed", "DECISION_ROUTED": "Route selected", "RETRY_SCHEDULED": "Retry scheduled", "HUMAN_REVIEW_REQUESTED": "Human review requested", "HUMAN_APPROVED": "Human approved", "HUMAN_REJECTED": "Human rejected", "WORKFLOW_RESUMED": "Workflow resumed", "WORKFLOW_COMPLETED": "Workflow completed", "WORKFLOW_FAILED": "Workflow failed closed", } EVENT_ICONS = { "WORKFLOW_STARTED": "▶", "NODE_STARTED": "→", "NODE_COMPLETED": "✓", "NODE_FAILED": "×", "NODE_SKIPPED": "↷", "DECISION_ROUTED": "⇢", "RETRY_SCHEDULED": "↻", "HUMAN_REVIEW_REQUESTED": "👤", "HUMAN_APPROVED": "✓", "HUMAN_REJECTED": "■", "WORKFLOW_RESUMED": "▶", "WORKFLOW_COMPLETED": "✓", "WORKFLOW_FAILED": "×", } APP_CSS = """ .gradio-container { max-width:1120px !important; margin:0 auto !important; } .agent-hero { padding:1.65rem 1.75rem; border:1px solid var(--border-color-primary,rgba(127,127,127,.25)); border-radius:22px; background:linear-gradient(135deg,rgba(249,115,22,.12),rgba(99,102,241,.08)); margin-bottom:1rem; } .agent-eyebrow,.outcome-eyebrow,.panel-eyebrow { font-size:.76rem; font-weight:800; letter-spacing:.12em; opacity:.72; margin-bottom:.35rem; } .agent-hero h1 { margin:.25rem 0 .55rem; font-size:2.12rem; line-height:1.16; max-width:820px; } .agent-hero p { margin:0; max-width:820px; font-size:1.06rem; line-height:1.58; } .pattern-grid { display:grid; grid-template-columns:1fr; gap:.65rem; margin:1rem 0; } .pattern-card,.ai-result,.why-panel { padding:1rem 1.1rem; border-radius:14px; border:1px solid var(--border-color-primary,rgba(127,127,127,.25)); background:var(--block-background-fill,rgba(127,127,127,.06)); } .pattern-card strong { display:block; margin-bottom:.3rem; font-size:1.04rem; } .pattern-card span { opacity:.80; line-height:1.48; font-size:.96rem; } .ai-card { border-color:rgba(59,130,246,.55); background:linear-gradient(135deg,rgba(59,130,246,.14),rgba(99,102,241,.09)); } .ai-runtime { padding:1rem 1.1rem; border-radius:14px; border:1px solid rgba(59,130,246,.38); background:rgba(59,130,246,.08); margin:.7rem 0 1rem; line-height:1.5; } .ai-runtime-live { border-color:rgba(34,197,94,.45); background:rgba(34,197,94,.08); } .ai-runtime-waiting { border-color:rgba(245,158,11,.45); background:rgba(245,158,11,.08); } .pattern-flow { display:flex; flex-direction:column; align-items:stretch; gap:.35rem; margin:.8rem 0 1.2rem; } .flow-pill { padding:.7rem .85rem; border-radius:12px; border:1px solid var(--border-color-primary,rgba(127,127,127,.25)); background:var(--block-background-fill,rgba(127,127,127,.06)); font-weight:700; font-size:.96rem; } .ai-pill { border-color:rgba(59,130,246,.6); background:rgba(59,130,246,.12); } .flow-arrow { align-self:center; opacity:.5; font-weight:800; transform:rotate(90deg); line-height:1; } .section-note { padding:.9rem 1rem; border-radius:12px; background:rgba(99,102,241,.08); border:1px solid rgba(99,102,241,.18); margin-bottom:.85rem; line-height:1.5; } .business-outcome { border-radius:16px; padding:1.1rem 1.2rem; border:1px solid var(--border-color-primary,rgba(127,127,127,.25)); margin:.8rem 0; } .outcome-success { border-left:6px solid #22c55e; background:rgba(34,197,94,.08); } .outcome-waiting { border-left:6px solid #f59e0b; background:rgba(245,158,11,.08); } .outcome-rejected { border-left:6px solid #f97316; background:rgba(249,115,22,.08); } .outcome-failed { border-left:6px solid #ef4444; background:rgba(239,68,68,.08); } .outcome-neutral { border-left:6px solid #64748b; background:rgba(100,116,139,.08); } .outcome-title,.panel-title { font-size:1.2rem; font-weight:800; margin-bottom:.4rem; } .outcome-body,.panel-body { line-height:1.5; margin-bottom:.55rem; } .outcome-takeaway { font-weight:650; opacity:.83; } .ai-result-live { border-color:rgba(59,130,246,.6); background:rgba(59,130,246,.09); } .ai-result-fallback { border-color:rgba(100,116,139,.4); } .ai-result-failed { border-color:rgba(239,68,68,.45); background:rgba(239,68,68,.07); } .ai-mode { display:inline-block; padding:.25rem .5rem; border-radius:999px; font-size:.76rem; font-weight:800; background:rgba(59,130,246,.14); margin-bottom:.45rem; } .ai-model { font-size:.82rem; opacity:.7; margin-bottom:.5rem; } .ai-category { margin-bottom:.5rem; } .ai-summary { line-height:1.48; margin-bottom:.6rem; } .ai-used { font-weight:700; margin-bottom:.45rem; } .ai-boundary,.why-proof { font-size:.88rem; opacity:.78; line-height:1.4; } .why-standard { border-left:5px solid #22c55e; } .why-review { border-left:5px solid #f59e0b; } .why-list { margin:.35rem 0 .7rem 1.15rem; } .workflow-map { margin:1rem 0; padding:1rem 1.05rem; border-radius:16px; border:1px solid var(--border-color-primary,rgba(127,127,127,.25)); background:var(--block-background-fill,rgba(127,127,127,.04)); } .map-heading,.journey-heading { font-size:1.15rem; font-weight:800; } .map-subheading,.journey-subheading { opacity:.72; margin:.25rem 0 .8rem; line-height:1.45; } .map-main { display:flex; flex-wrap:wrap; align-items:center; gap:.42rem; } .map-split { display:grid; grid-template-columns:1fr; gap:.75rem; margin-top:.85rem; } .map-branch { padding:.75rem; border-radius:12px; border:1px dashed var(--border-color-primary,rgba(127,127,127,.28)); } .branch-label { font-size:.72rem; font-weight:800; letter-spacing:.08em; opacity:.65; margin-bottom:.45rem; } .map-node { display:inline-block; padding:.42rem .62rem; border-radius:10px; border:1px solid rgba(100,116,139,.35); background:rgba(100,116,139,.08); font-size:.84rem; font-weight:700; } .map-node-completed { border-color:rgba(34,197,94,.55); background:rgba(34,197,94,.12); } .map-node-waiting-for-human,.map-node-retry-scheduled,.map-node-running { border-color:rgba(245,158,11,.6); background:rgba(245,158,11,.12); } .map-node-failed { border-color:rgba(239,68,68,.6); background:rgba(239,68,68,.12); } .map-node-skipped,.map-node-pending,.map-node-ready { opacity:.42; } .map-node-ai { box-shadow:inset 0 0 0 2px rgba(59,130,246,.62); } .map-arrow { opacity:.5; font-weight:800; } .map-legend { margin-top:.8rem; font-size:.8rem; opacity:.65; } .journey-wrap { padding:1rem 0 .2rem; } .journey-grid { display:grid; grid-template-columns:1fr; gap:.65rem; } .journey-step { display:flex; gap:.7rem; padding:.85rem .9rem; border-radius:12px; border:1px solid var(--border-color-primary,rgba(127,127,127,.22)); background:var(--block-background-fill,rgba(127,127,127,.04)); } .journey-icon { width:30px; height:30px; min-width:30px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-weight:900; } .journey-done { background:rgba(34,197,94,.16); } .journey-waiting { background:rgba(245,158,11,.18); } .journey-rejected { background:rgba(249,115,22,.18); } .journey-failed { background:rgba(239,68,68,.18); } .journey-skipped { background:rgba(100,116,139,.16); } .journey-pending { background:rgba(100,116,139,.10); } .journey-title { font-weight:750; } .journey-state { font-size:.8rem; font-weight:700; opacity:.78; margin:.1rem 0 .2rem; } .journey-description { font-size:.9rem; opacity:.74; line-height:1.42; } .activity-card { border:1px solid rgba(59,130,246,.30); border-radius:18px; padding:17px 19px; margin:14px 0 18px; background:linear-gradient(135deg,rgba(59,130,246,.08),rgba(99,102,241,.035)); } .activity-head { display:flex; align-items:center; gap:10px; margin-bottom:8px; } .activity-spinner { width:24px; height:24px; box-sizing:border-box; border:4px solid rgba(59,130,246,.18); border-top-color:#3b82f6; border-right-color:#6366f1; border-radius:50%; animation:workflow-spin .78s linear infinite; flex:0 0 auto; } .activity-badge { display:inline-block; border:1px solid rgba(59,130,246,.42); border-radius:999px; padding:4px 8px; font-size:.72rem; font-weight:850; letter-spacing:.09em; } .activity-title { font-size:1.07rem; font-weight:800; } .activity-sub { font-size:.92rem; opacity:.79; line-height:1.4; margin-bottom:10px; } .activity-track { height:8px; background:rgba(148,163,184,.18); border-radius:999px; overflow:hidden; margin:10px 0 13px; } .activity-fill { height:100%; background:linear-gradient(90deg,#3b82f6,#6366f1); transition:width .2s ease; } .activity-track.indeterminate .activity-fill { width:34%; animation:workflow-slide 1.05s ease-in-out infinite; } .activity-feed { display:grid; gap:6px; } .activity-feed.activity-scroll { max-height:430px; overflow-y:auto; padding-right:7px; scrollbar-gutter:stable; } .activity-event { display:grid; grid-template-columns:28px minmax(0,1fr); gap:8px; padding-top:8px; border-top:1px solid rgba(148,163,184,.16); } .activity-event:first-child { border-top:0; padding-top:0; } .activity-icon { font-weight:850; line-height:1.45; text-align:center; } .activity-main { font-size:.94rem; line-height:1.4; } .activity-main strong { font-weight:800; } .activity-meta { font-size:.78rem; opacity:.66; margin-top:2px; } .activity-complete { border-color:rgba(34,197,94,.35); background:linear-gradient(135deg,rgba(34,197,94,.08),rgba(59,130,246,.035)); } .activity-scroll-note { font-size:.82rem; opacity:.72; margin-bottom:8px; } @keyframes workflow-spin { to { transform:rotate(360deg); } } @keyframes workflow-slide { 0% { transform:translateX(-110%); } 50% { transform:translateX(205%); } 100% { transform:translateX(-110%); } } @media (max-width:700px) { .gradio-container { max-width:100% !important; } .agent-hero { padding:1.3rem 1.1rem; } .agent-hero h1 { font-size:1.75rem; } } """ HERO_HTML = """
A fictional wealth-management operations team needs to move a new household through onboarding. AI may organize the unstructured intake into useful work product, but application code controls sequencing, retries, routing, persistence, and the human-review boundary.