File size: 3,762 Bytes
06947bf
 
26401b4
906d397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26401b4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import patch_gradio_jsonschema  # MUST be first - patches boolean JSON Schema handling
import patch_gradio_jsonschema  # MUST be first - patches boolean JSON Schema handling
import patch_gradio_jsonschema  # MUST be first - patches boolean JSON Schema handling\n
# app.py (Updated with Triage Orchestration)

import os
import math
from flask import Flask, render_template, request, jsonify
from dotenv import load_dotenv
from graph import triage_app, planner_app, main_app # Import all three compiled apps
from utils import generate_mermaid_diagram

load_dotenv()
app = Flask(__name__)

# Create necessary directories on startup
os.makedirs("outputs", exist_ok=True)
os.makedirs("uploads", exist_ok=True)
os.makedirs("memory", exist_ok=True)
os.makedirs("logs", exist_ok=True)


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/estimate', methods=['POST'])
def estimate():
    data = request.json
    user_input = data.get('message', '').strip()
    if not user_input:
        return jsonify({"error": "Message cannot be empty."}), 400
    
    # --- NEW TRIAGE STEP ---
    # First, check if the input is a simple greeting
    triage_inputs = {"userInput": user_input}
    triage_result = triage_app.invoke(triage_inputs)
    
    # If the triage agent provided a direct response, it's a greeting.
    if triage_result.get("draftResponse"):
        # We add a special key to let the frontend know to just display the message
        return jsonify({"is_greeting": True, "response": triage_result["draftResponse"]})

    # --- If not a greeting, proceed to the planner ---
    planner_inputs = {"userInput": user_input}
    try:
        estimate_result = planner_app.invoke(planner_inputs)
        estimate_result['pmPlan']['is_greeting'] = False
        return jsonify(estimate_result.get('pmPlan', {}))
    except Exception as e:
        return jsonify({"error": "An unexpected error occurred during planning."}), 500


@app.route('/chat', methods=['POST'])
def chat():
    data = request.json
    user_input = data.get('message', '').strip()
    
    try:
        user_budget = float(data.get('user_budget', 0.0))
        cost_per_loop = float(data.get('cost_per_loop', 0.05))
    except (ValueError, TypeError):
        return jsonify({"error": "Invalid budget or cost format."}), 400

    if not user_input:
        return jsonify({"error": "Message cannot be empty."}), 400

    if cost_per_loop > 0:
        total_runs_affordable = max(1, math.floor(user_budget / cost_per_loop))
        max_loops_calibrated = total_runs_affordable - 1
    else:
        max_loops_calibrated = 0

    initial_state = {
        "userInput": user_input, "chatHistory": [], "coreObjectivePrompt": "",
        "retrievedMemory": "", "pmPlan": {}, "experimentCode": None,
        "experimentResults": None, "draftResponse": "", "qaFeedback": None,
        "approved": False, "execution_path": [], "rework_cycles": 0,
        "max_loops": max_loops_calibrated
    }
    
    try:
        final_state = main_app.invoke(initial_state)
    except Exception as e:
        return jsonify({"response": "An unexpected error occurred during execution. Please check the logs."}), 500
    
    run_path = final_state.get('execution_path', [])
    if run_path:
        mermaid_syntax = generate_mermaid_diagram(run_path)
        with open("outputs/last_run_flow.md", "w") as f:
            f.write("# Last Run Execution Flow\n\n")
            f.write("```mermaid\n")
            f.write(mermaid_syntax)
            f.write("```\n")
            
    response = final_state.get('draftResponse', "An error occurred, and no response was generated.")
    return jsonify({"response": response})

if __name__ == '__main__':
    app.run(debug=True, port=5001)