UzbekLider commited on
Commit
7e9ef9c
·
verified ·
1 Parent(s): 13aa6d4

Update core/planner.py

Browse files
Files changed (1) hide show
  1. core/planner.py +49 -61
core/planner.py CHANGED
@@ -1,70 +1,58 @@
 
 
1
  import json
2
  import logging
3
- import re
4
- from dataclasses import dataclass, field
5
- from typing import Optional
6
  from models.router import ModelRouter
7
 
8
- log = logging.getLogger("planner")
9
-
10
- PLAN_SYSTEM = """You are an expert software architect. Break down a coding task into concrete steps.
11
- Output ONLY a JSON array of steps. Each step object must have:
12
- - "id": number (1, 2, 3...)
13
- - "title": short title (max 8 words)
14
- - "type": one of: plan, code, test, debug, fix, review, shell
15
- - "description": clear explanation of what to do
16
- - "files": list of files to create/modify
17
- - "needs_input": true if you need info from owner
18
- - "input_question": question string if needs_input is true
19
-
20
- Output ONLY the JSON array. No markdown, no explanations."""
21
-
22
-
23
- @dataclass
24
- class TaskStep:
25
- id: int
26
- title: str
27
- type: str
28
- description: str
29
- files: list[str] = field(default_factory=list)
30
- needs_input: bool = False
31
- input_question: Optional[str] = None
32
- status: str = "pending"
33
- result: Optional[str] = None
34
- error: Optional[str] = None
35
-
36
-
37
- @dataclass
38
- class TaskPlan:
39
- task: str
40
- steps: list[TaskStep]
41
- project_dir: str
42
-
43
 
44
  class TaskPlanner:
45
- def __init__(self, model_router: ModelRouter):
46
- self.router = model_router
47
-
48
- async def create_plan(self, task: str, project_dir: str) -> TaskPlan:
49
- log.info(f"Creating plan for: {task[:80]}")
50
- prompt = f"Task: {task}\nProject Directory: {project_dir}"
51
-
52
- raw = await self.router.call(
53
- prompt=prompt, task_type="plan", system=PLAN_SYSTEM, estimated_tokens=1200
 
 
 
 
 
54
  )
55
 
56
- steps = self._parse_steps(raw)
57
- return TaskPlan(task=task, steps=steps, project_dir=project_dir)
58
-
59
- def _parse_steps(self, raw: str) -> list[TaskStep]:
60
- clean = re.sub(r"
61
- http://googleusercontent.com/immersive_entry_chip/0
62
-
63
- ---
64
 
65
- ## 🛠️ Execution Checklist
66
- 1. Save and update these configuration values inside your Hugging Face Space **Variables and Secrets** settings panel:
67
- * `TELEGRAM_BOT_TOKEN`, `TELEGRAM_OWNER_ID`
68
- * `GROQ_API_KEY`, `GEMINI_API_KEY`
69
- * `GITHUB_TOKEN`, `GITHUB_REPO`
70
- 2. Save and commit your files. Hugging Face will automatically boot your Docker container, open the required listening port, and connect straight to Telegram!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
  import json
4
  import logging
5
+ from typing import List, Dict, Any
 
 
6
  from models.router import ModelRouter
7
 
8
+ log = logging.getLogger("core")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  class TaskPlanner:
11
+ def __init__(self, router: ModelRouter):
12
+ self.router = router
13
+
14
+ async def generate_plan(self, task_description: str) -> List[Dict[str, Any]]:
15
+ system_prompt = (
16
+ "You are an expert software architect. Break down the user request into a strict sequential "
17
+ "execution plan. Respond ONLY with a valid JSON array of step objects. Do not wrap in markdown tags.\n"
18
+ "Each step object must have:\n"
19
+ "- step_id: integer\n"
20
+ "- task_type: text (one of: 'code', 'debug', 'review', 'explain', 'fix', 'test', 'generic')\n"
21
+ "- target_file: text (the path to the file being touched)\n"
22
+ "- instruction: text (detailed objective for this step)\n"
23
+ "Example format:\n"
24
+ '[{"step_id": 1, "task_type": "code", "target_file": "math.py", "instruction": "Write sum function"}]'
25
  )
26
 
27
+ user_prompt = f"Task Description: {task_description}"
28
+
29
+ raw_response = await self.router.call(
30
+ prompt=user_prompt,
31
+ task_type="plan",
32
+ system=system_prompt,
33
+ estimated_tokens=1000
34
+ )
35
 
36
+ return self._parse_json_plan(raw_response)
37
+
38
+ def _parse_json_plan(self, text: str) -> List[Dict[str, Any]]:
39
+ # TO'G'RILANDI: regex qatorlari yopildi va xatolik bartaraf etildi
40
+ clean = re.sub(r"```json\s*", "", text, flags=re.IGNORECASE)
41
+ clean = re.sub(r"```\s*$", "", clean, flags=re.IGNORECASE)
42
+ clean = clean.strip()
43
+
44
+ try:
45
+ plan = json.loads(clean)
46
+ if isinstance(plan, list):
47
+ return plan
48
+ elif isinstance(plan, dict) and "steps" in plan:
49
+ return plan["steps"]
50
+ raise ValueError("JSON is not a list structure.")
51
+ except Exception as e:
52
+ log.error(f"Failed to parse plan JSON. Raw output: {text}. Error: {e}")
53
+ return [{
54
+ "step_id": 1,
55
+ "task_type": "generic",
56
+ "target_file": "unknown_file.py",
57
+ "instruction": f"Execute raw request due to planner parsing error. Task: {text}"
58
+ }]