CoolFace
Apppublic

cjoyy/ops-agent

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
app.py114 linesDownload Raw Back to root
1from uuid import uuid42 3import gradio as gr4from langgraph.checkpoint.sqlite import SqliteSaver5from langgraph.types import Command6 7from graph_supervisor import get_app, get_message_content8from main import build_initial_state9 10 11def format_interrupt(interrupts) -> str:12    if not interrupts:13        return "Graph paused, but no interrupt payload was returned."14 15    payload = interrupts[0].value16    return (17        "Security approval required\n\n"18        f"Action: {payload.get('action')}\n"19        f"Ticket summary: {payload.get('ticket_summary')}\n"20        f"Proposed action: {payload.get('proposed_action')}"21    )22 23 24def format_final_result(result: dict) -> str:25    return (26        f"Category: {result.get('category')}\n"27        f"Resolved categories: {result.get('resolved_categories', [])}\n\n"28        f"{get_message_content(result['messages'][-1])}"29    )30 31 32def run_ticket(ticket: str):33    if not ticket.strip():34        return "Please enter a ticket.", None, gr.update(visible=False), gr.update(visible=False)35 36    thread_id = f"space-{uuid4()}"37    config = {"configurable": {"thread_id": thread_id}}38 39    with SqliteSaver.from_conn_string("checkpoints.sqlite") as checkpointer:40        app = get_app(checkpointer)41        result = app.invoke(build_initial_state(ticket), config=config)42 43    if "__interrupt__" in result:44        return (45            format_interrupt(result["__interrupt__"]),46            thread_id,47            gr.update(visible=True),48            gr.update(visible=True),49        )50 51    return format_final_result(result), None, gr.update(visible=False), gr.update(visible=False)52 53 54def resume_ticket(thread_id: str, approved: bool):55    if not thread_id:56        return "No paused security ticket to resume.", None, gr.update(visible=False), gr.update(visible=False)57 58    config = {"configurable": {"thread_id": thread_id}}59 60    with SqliteSaver.from_conn_string("checkpoints.sqlite") as checkpointer:61        app = get_app(checkpointer)62        result = app.invoke(Command(resume={"approved": approved}), config=config)63 64    if "__interrupt__" in result:65        return (66            format_interrupt(result["__interrupt__"]),67            thread_id,68            gr.update(visible=True),69            gr.update(visible=True),70        )71 72    return format_final_result(result), None, gr.update(visible=False), gr.update(visible=False)73 74 75with gr.Blocks(title="Ops Agent") as demo:76    gr.Markdown("# Ops Agent")77    gr.Markdown(78        "Multi-agent IT/ops assistant with LangGraph routing, RAG runbooks, tools, "79        "human approval, and SQLite checkpointing."80    )81 82    ticket = gr.Textbox(83        label="Ticket",84        placeholder="Service auth-api saya stuck, gimana cara restart yang benar?",85        lines=4,86    )87    submit = gr.Button("Run Ticket", variant="primary")88    output = gr.Textbox(label="Result", lines=14)89    thread_state = gr.State(None)90 91    with gr.Row():92        approve = gr.Button("Approve Security Action", visible=False)93        reject = gr.Button("Reject Security Action", visible=False)94 95    submit.click(96        run_ticket,97        inputs=[ticket],98        outputs=[output, thread_state, approve, reject],99    )100    approve.click(101        lambda thread_id: resume_ticket(thread_id, True),102        inputs=[thread_state],103        outputs=[output, thread_state, approve, reject],104    )105    reject.click(106        lambda thread_id: resume_ticket(thread_id, False),107        inputs=[thread_state],108        outputs=[output, thread_state, approve, reject],109    )110 111 112if __name__ == "__main__":113    demo.launch(server_name="0.0.0.0", server_port=7860)114