|
20 | 20 | import os |
21 | 21 | from datetime import datetime |
22 | 22 | from pathlib import Path |
| 23 | +from uuid import UUID |
23 | 24 |
|
24 | 25 | # Load environment variables from .env file |
25 | 26 | from dotenv import load_dotenv |
|
35 | 36 |
|
36 | 37 | # CSV ticket service |
37 | 38 | from csv_data import Ticket, get_csv_ticket_service |
| 39 | +from usecase_demo import UsecaseDemoRunCreate, usecase_demo_run_service |
38 | 40 |
|
39 | 41 | # FastMCP client for direct ticket MCP calls (no AI) |
40 | 42 | from fastmcp import Client as MCPClient |
41 | 43 | from mcp_handler import handle_mcp_request |
42 | 44 | from operations import ( |
| 45 | + CSV_TICKET_FIELDS, |
43 | 46 | op_create_task, |
44 | 47 | op_delete_task, |
45 | 48 | op_get_task, |
@@ -177,6 +180,47 @@ async def rest_run_agent(): |
177 | 180 | return jsonify({"error": str(e)}), 500 |
178 | 181 |
|
179 | 182 |
|
| 183 | +# ============================================================================ |
| 184 | +# USECASE DEMO AGENT RUN ENDPOINTS |
| 185 | +# ============================================================================ |
| 186 | + |
| 187 | +@app.route("/api/usecase-demo/agent-runs", methods=["POST"]) |
| 188 | +async def create_usecase_demo_agent_run(): |
| 189 | + """Queue a background agent run using the provided prompt.""" |
| 190 | + try: |
| 191 | + data = await request.get_json() or {} |
| 192 | + payload = UsecaseDemoRunCreate(**data) |
| 193 | + run = await usecase_demo_run_service.create_run(payload) |
| 194 | + return jsonify(run.model_dump(mode="json")), 202 |
| 195 | + except ValidationError as e: |
| 196 | + return jsonify({"error": str(e)}), 400 |
| 197 | + except Exception as e: |
| 198 | + return jsonify({"error": str(e)}), 500 |
| 199 | + |
| 200 | + |
| 201 | +@app.route("/api/usecase-demo/agent-runs", methods=["GET"]) |
| 202 | +async def list_usecase_demo_agent_runs(): |
| 203 | + """List recent background agent runs.""" |
| 204 | + try: |
| 205 | + limit = request.args.get("limit", default=20, type=int) |
| 206 | + runs = await usecase_demo_run_service.list_runs(limit=limit or 20) |
| 207 | + return jsonify({"runs": [run.model_dump(mode="json") for run in runs]}), 200 |
| 208 | + except Exception as e: |
| 209 | + return jsonify({"error": str(e)}), 500 |
| 210 | + |
| 211 | + |
| 212 | +@app.route("/api/usecase-demo/agent-runs/<run_id>", methods=["GET"]) |
| 213 | +async def get_usecase_demo_agent_run(run_id: str): |
| 214 | + """Fetch one background run by ID.""" |
| 215 | + try: |
| 216 | + run = await usecase_demo_run_service.get_run(run_id) |
| 217 | + if run is None: |
| 218 | + return jsonify({"error": "Run not found"}), 404 |
| 219 | + return jsonify(run.model_dump(mode="json")), 200 |
| 220 | + except Exception as e: |
| 221 | + return jsonify({"error": str(e)}), 500 |
| 222 | + |
| 223 | + |
180 | 224 | # ============================================================================ |
181 | 225 | # TICKET MCP EXAMPLE - Direct FastMCP client usage (no AI) |
182 | 226 | # ============================================================================ |
@@ -403,31 +447,6 @@ async def get_qa_tickets(): |
403 | 447 | print(f"📊 Loaded {_csv_loaded} tickets from CSV") |
404 | 448 |
|
405 | 449 |
|
406 | | -# Define which fields are available for display |
407 | | -CSV_TICKET_FIELDS = [ |
408 | | - {"name": "id", "label": "ID", "type": "uuid"}, |
409 | | - {"name": "summary", "label": "Summary", "type": "string"}, |
410 | | - {"name": "status", "label": "Status", "type": "enum"}, |
411 | | - {"name": "priority", "label": "Priority", "type": "enum"}, |
412 | | - {"name": "assignee", "label": "Assignee", "type": "string"}, |
413 | | - {"name": "assigned_group", "label": "Assigned Group", "type": "string"}, |
414 | | - {"name": "requester_name", "label": "Requester", "type": "string"}, |
415 | | - {"name": "requester_email", "label": "Email", "type": "string"}, |
416 | | - {"name": "city", "label": "City", "type": "string"}, |
417 | | - {"name": "country", "label": "Country", "type": "string"}, |
418 | | - {"name": "service", "label": "Service", "type": "string"}, |
419 | | - {"name": "incident_type", "label": "Incident Type", "type": "string"}, |
420 | | - {"name": "product_name", "label": "Product", "type": "string"}, |
421 | | - {"name": "manufacturer", "label": "Manufacturer", "type": "string"}, |
422 | | - {"name": "created_at", "label": "Created", "type": "datetime"}, |
423 | | - {"name": "updated_at", "label": "Updated", "type": "datetime"}, |
424 | | - {"name": "urgency", "label": "Urgency", "type": "string"}, |
425 | | - {"name": "impact", "label": "Impact", "type": "string"}, |
426 | | - {"name": "resolution", "label": "Resolution", "type": "string"}, |
427 | | - {"name": "notes", "label": "Notes", "type": "string"}, |
428 | | -] |
429 | | - |
430 | | - |
431 | 450 | @app.route("/api/csv-tickets/fields", methods=["GET"]) |
432 | 451 | async def get_csv_ticket_fields(): |
433 | 452 | """Get metadata about available CSV ticket fields.""" |
@@ -539,6 +558,46 @@ def get_sort_key(ticket: Ticket): |
539 | 558 | }) |
540 | 559 |
|
541 | 560 |
|
| 561 | +@app.route("/api/csv-tickets/<ticket_id>", methods=["GET"]) |
| 562 | +async def get_csv_ticket(ticket_id: str): |
| 563 | + """ |
| 564 | + Get one CSV ticket by ID. |
| 565 | +
|
| 566 | + Query params: |
| 567 | + - fields: optional comma-separated list of fields to include |
| 568 | + """ |
| 569 | + try: |
| 570 | + parsed_id = UUID(ticket_id) |
| 571 | + except ValueError: |
| 572 | + return jsonify({"error": "Invalid ticket ID"}), 400 |
| 573 | + |
| 574 | + ticket = _csv_ticket_service.get_ticket(parsed_id) |
| 575 | + if ticket is None: |
| 576 | + return jsonify({"error": "Ticket not found"}), 404 |
| 577 | + |
| 578 | + fields_param = request.args.get("fields", "") |
| 579 | + if fields_param: |
| 580 | + selected_fields = [f.strip() for f in fields_param.split(",") if f.strip()] |
| 581 | + else: |
| 582 | + selected_fields = list(ticket.model_fields.keys()) |
| 583 | + |
| 584 | + result = {} |
| 585 | + for field in selected_fields: |
| 586 | + val = getattr(ticket, field, None) |
| 587 | + if val is None: |
| 588 | + result[field] = None |
| 589 | + elif hasattr(val, "value"): |
| 590 | + result[field] = val.value |
| 591 | + elif hasattr(val, "isoformat"): |
| 592 | + result[field] = val.isoformat() |
| 593 | + elif hasattr(val, "hex"): |
| 594 | + result[field] = str(val) |
| 595 | + else: |
| 596 | + result[field] = val |
| 597 | + |
| 598 | + return jsonify(result), 200 |
| 599 | + |
| 600 | + |
542 | 601 | @app.route("/api/csv-tickets/stats", methods=["GET"]) |
543 | 602 | async def get_csv_ticket_stats(): |
544 | 603 | """Get statistics about CSV tickets.""" |
|
0 commit comments