| import json |
| import gradio as gr |
| from server.environment import RevOpsEnvironment |
| from models import RevOpsAction, ActionType |
|
|
| env = RevOpsEnvironment() |
| env.reset(task_id="task_easy") |
|
|
| def format_lead(obs): |
| if not obs or not hasattr(obs, 'lead'): |
| return "No lead data." |
| lead = obs.lead |
| return f"""### Current Lead |
| **ID**: {lead.id} |
| **Name**: {lead.name} |
| **Title**: {lead.title} |
| **Email**: {lead.email} |
| **Company**: {lead.company} |
| **Source**: {lead.source} |
| **Message**: {lead.message} |
| **Score**: {lead.score}""" |
|
|
| def format_enrichment(obs): |
| if not obs or not obs.enrichment.enriched: |
| return "Not Enriched Yet." |
| e = obs.enrichment |
| return f"""### Firmographic Data |
| **Company Size**: {e.company_size} |
| **Revenue**: {e.revenue} |
| **Industry**: {e.industry} |
| **Region**: {e.region} |
| **Tier**: {e.tier}""" |
|
|
| def format_crm(obs): |
| if not obs or not obs.crm.checked: |
| return "CRM Not Checked." |
| accounts = obs.crm.existing_accounts |
| opps = obs.crm.opportunities |
| |
| res = "### CRM Match Results\n" |
| if not accounts and not opps: |
| return res + "No existing CRM records found." |
| |
| if accounts: |
| res += "#### Existing Accounts:\n" |
| for a in accounts: |
| res += f"- {a.get('name')} (ID: {a.get('account_id')})\n" |
| |
| if opps: |
| res += "\n#### Opportunities:\n" |
| for o in opps: |
| res += f"- Opp ID: {o.opportunity_id} | Status: {o.status} | Amount: ${o.amount} | Assigned Rep: {o.assigned_rep_id}\n" |
| return res |
|
|
| def refresh_ui(): |
| st = env.get_full_state() |
| obs = env._get_observation() |
| done = obs.done if hasattr(obs, 'done') else False |
| |
| feedback = st.get("last_feedback", "") |
| score = st.get("grader_score") |
| |
| status_text = f"**Status**: {'DONE' if done else 'IN PROGRESS'}\n\n**Accumulated Reward**: {st.get('accumulated_reward', 0.0):.2f}" |
| if score is not None: |
| status_text += f"\n\n**Final Grader Score**: {score}" |
| |
| return ( |
| format_lead(obs), |
| format_enrichment(obs), |
| format_crm(obs), |
| feedback, |
| status_text |
| ) |
|
|
| def reset_task(task_id): |
| env.reset(task_id=task_id) |
| return refresh_ui() |
|
|
| def perform_action(action_type, score, rep_id, account_id, opportunity_id, disqualification_reason): |
| st = env.get_full_state() |
| if st.get("current_lead_index", 0) >= len(st.get("leads", [])): |
| return refresh_ui() |
| |
| |
| action_val = ActionType(action_type) |
| |
| action = RevOpsAction( |
| action_type=action_val, |
| score=int(score) if score else None, |
| rep_id=rep_id if rep_id else None, |
| account_id=account_id if account_id else None, |
| opportunity_id=opportunity_id if opportunity_id else None, |
| disqualification_reason=disqualification_reason if disqualification_reason else None |
| ) |
| |
| env.step(action) |
| return refresh_ui() |
|
|
| |
| with gr.Blocks(title="RevOps CRM Agent Desktop", theme=gr.themes.Soft()) as demo: |
| gr.Markdown("# 🏢 RevOps-Agent Live Dashboard") |
| gr.Markdown("Interact with the OpenEnv OpenEnv backend as a human operator, or watch your agent's live states.") |
| |
| with gr.Row(): |
| with gr.Column(scale=2): |
| task_dropdown = gr.Dropdown(choices=["task_easy", "task_medium", "task_hard"], value="task_easy", label="Select Simulation Scenario") |
| reset_btn = gr.Button("Reset Environment", variant="primary") |
| |
| with gr.Column(scale=1): |
| status_box = gr.Markdown(value="**Status**: IN PROGRESS\n**Accumulated Reward**: 0.00") |
| |
| with gr.Row(): |
| with gr.Column(scale=1): |
| lead_box = gr.Markdown() |
| with gr.Column(scale=1): |
| enrichment_box = gr.Markdown() |
| with gr.Column(scale=1): |
| crm_box = gr.Markdown() |
| |
| with gr.Row(): |
| feedback_box = gr.Textbox(label="Last Action Feedback", interactive=False) |
| |
| gr.Markdown("---") |
| gr.Markdown("### ⚡ Action Console") |
| with gr.Row(): |
| with gr.Column(scale=1): |
| action_dropdown = gr.Dropdown(choices=[e.value for e in ActionType], value="enrich_lead", label="Action Type") |
| btn_submit = gr.Button("Execute Action", variant="primary") |
| |
| with gr.Column(scale=2): |
| score_input = gr.Number(label="Score (0-100) - For update_lead_score") |
| rep_id_input = gr.Textbox(label="Rep ID - For route_to_rep (e.g., rep_amer_mm, rep_emea_ent)") |
| account_id_input = gr.Textbox(label="Account ID - For merge_with_account") |
| opp_id_input = gr.Textbox(label="Opportunity ID - For flag_reengagement") |
| disqualify_input = gr.Textbox(label="Disqualification Reason - For disqualify") |
|
|
| |
| outputs = [lead_box, enrichment_box, crm_box, feedback_box, status_box] |
| |
| demo.load(refresh_ui, inputs=None, outputs=outputs) |
| |
| reset_btn.click(reset_task, inputs=[task_dropdown], outputs=outputs) |
| |
| btn_submit.click( |
| perform_action, |
| inputs=[action_dropdown, score_input, rep_id_input, account_id_input, opp_id_input, disqualify_input], |
| outputs=outputs |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch(server_name="0.0.0.0", server_port=7860) |
|
|