File size: 2,543 Bytes
316caac
 
 
 
 
 
 
b89676e
 
 
 
316caac
 
 
 
 
b89676e
316caac
 
 
 
b9aedf5
b89676e
 
 
 
 
b9aedf5
 
316caac
 
 
 
 
 
 
 
 
b9aedf5
 
b89676e
b9aedf5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
316caac
b9aedf5
 
 
 
 
316caac
b9aedf5
b89676e
b9aedf5
 
 
 
 
 
 
 
 
b89676e
 
 
 
 
b9aedf5
 
b89676e
 
b9aedf5
 
 
 
 
b89676e
b9aedf5
 
 
 
b89676e
 
 
 
 
 
 
b9aedf5
 
 
 
 
b89676e
b9aedf5
b89676e
b9aedf5
 
b89676e
 
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
103
104
105
106
107
108
109
110
111
112
113
import requests
import json
from config import Config


def create_plan(goal: str):
    """
    Robust AI planner:
    - safe LLM call
    - strict JSON parsing
    - fallback protection
    """

    prompt = f"""
You are a planning agent.

Break the goal into executable steps.

GOAL:
{goal}

RULES:
- Output ONLY valid JSON
- NO explanation
- NO markdown
- NO extra text
- steps must be simple actionable instructions

FORMAT:
{{
  "steps": [
    "step 1",
    "step 2",
    "step 3"
  ]
}}
"""

    try:
        # =========================
        # CALL LLM
        # =========================
        res = requests.post(
            Config.LLM_API_URL,
            headers={
                "Authorization": f"Bearer {Config.LLM_API_KEY}",
                "Content-Type": "application/json"
            },
            json={
                "model": Config.MODEL,
                "messages": [
                    {"role": "user", "content": prompt}
                ],
                "temperature": 0.2
            },
            timeout=30
        )

        # =========================
        # HTTP CHECK
        # =========================
        if res.status_code != 200:
            return {"steps": [goal]}

        # =========================
        # JSON PARSE SAFE
        # =========================
        try:
            data = res.json()
        except Exception:
            return {"steps": [goal]}

        if not isinstance(data, dict):
            return {"steps": [goal]}

        # =========================
        # EXTRACT CONTENT
        # =========================
        choices = data.get("choices")
        if not choices or not isinstance(choices, list):
            return {"steps": [goal]}

        message = choices[0].get("message", {})
        content = message.get("content", "")

        if not content:
            return {"steps": [goal]}

        # =========================
        # PARSE PLAN JSON
        # =========================
        try:
            parsed = json.loads(content)

            if (
                isinstance(parsed, dict)
                and "steps" in parsed
                and isinstance(parsed["steps"], list)
                and len(parsed["steps"]) > 0
            ):
                return parsed

        except Exception:
            pass

        # =========================
        # FALLBACK (SAFE)
        # =========================
        return {"steps": [goal]}

    except Exception:
        # HARD FAIL SAFE
        return {"steps": [goal]}