old intents
This commit is contained in:
+192
@@ -0,0 +1,192 @@
|
||||
class PlannerAgent:
|
||||
"""Агент-планировщик: анализирует проект и создаёт план подзадач."""
|
||||
|
||||
@staticmethod
|
||||
def plan(project: Project, user_task: str, errors: List[str] = None) -> List[Dict[str, str]]:
|
||||
# Получаем суммари из состояния
|
||||
summaries = project.state.get("file_summaries", {})
|
||||
if not summaries:
|
||||
print("⚠️ Нет описаний файлов. Сначала сгенерируйте их.")
|
||||
return [{"type": "error", "description": "Нет описаний файлов"}]
|
||||
|
||||
# Формируем текстовое представление суммари
|
||||
items = []
|
||||
for file_path, desc in summaries.items():
|
||||
items.append(f"- {file_path}: {desc}")
|
||||
summaries_text = "\n".join(items)
|
||||
|
||||
# Берём последние ошибки из состояния (если есть)
|
||||
errors_context = ""
|
||||
if errors:
|
||||
errors_context = "Актуальные ошибки в браузере:\n" + "\n".join(errors[:5])
|
||||
else:
|
||||
errors_context = "Ошибок в браузере не зафиксировано."
|
||||
# last_errors = project.state.get("last_errors", [])
|
||||
# errors_context = ""
|
||||
# if last_errors:
|
||||
# errors_context = "\n".join(last_errors[:3])
|
||||
|
||||
prompt = f"""
|
||||
Ты — главный архитектор. Получена задача: {user_task}
|
||||
|
||||
Вот краткое описание каждого важного файла проекта:
|
||||
{summaries_text}
|
||||
|
||||
{errors_context}
|
||||
|
||||
Твоя задача — составить план действий. План должен быть списком задач.
|
||||
Для каждой задачи укажи тип агента:
|
||||
- "test" — запустить браузер и проверить консоль на ошибки
|
||||
- "code" — написать или изменить код. Для этой задачи обязательно укажи поле "files" — массив относительных путей к файлам, которые нужно передать кодеру для контекста.
|
||||
- "browser" — открыть браузер для визуальной проверки (не обязательно)
|
||||
|
||||
План должен быть логичным: сначала обычно проверяют текущее состояние (test), затем исправляют ошибки (code), снова проверяют (test) и т.д.
|
||||
Но ты можешь предложить любую последовательность, которая, по твоему мнению, решит задачу.
|
||||
|
||||
Ответ дай строго в формате JSON-списка объектов:
|
||||
[
|
||||
{{"type": "test", "description": "описание задачи для тестировщика"}},
|
||||
{{"type": "code", "description": "описание задачи для кодера", "files": ["путь/к/файлу1", "путь/к/файлу2"]}}
|
||||
]
|
||||
Никаких пояснений, только JSON.
|
||||
"""
|
||||
messages = [{"role": "system", "content": "Ты — архитектор, выдаёшь только JSON."},
|
||||
{"role": "user", "content": prompt}]
|
||||
response = project.ollama_client.chat(messages, temperature=0.3)
|
||||
try:
|
||||
start = response.find('[')
|
||||
end = response.rfind(']') + 1
|
||||
if start != -1 and end != -1:
|
||||
json_str = response[start:end]
|
||||
plan = json.loads(json_str)
|
||||
if isinstance(plan, list) and all(
|
||||
isinstance(item, dict) and "type" in item and "description" in item for item in plan):
|
||||
for item in plan:
|
||||
if item["type"] == "code" and "files" not in item:
|
||||
item["files"] = [] # если не указано, ставим пустой массив
|
||||
return plan
|
||||
except Exception as e:
|
||||
print(f"Ошибка парсинга плана: {e}")
|
||||
# fallback
|
||||
return [{"type": "code", "description": "Не удалось создать план, попробуйте вручную.", "files": []}]
|
||||
|
||||
@staticmethod
|
||||
def replan(project: Project, user_task: str, errors: List[str]) -> List[Dict[str, str]]:
|
||||
"""Анализирует ошибки и возвращает список новых задач для их исправления."""
|
||||
summaries = project.state.get("file_summaries", {})
|
||||
summaries_text = "\n".join([f"- {p}: {d}" for p, d in summaries.items()])
|
||||
errors_text = "\n".join(errors) # ограничим для контекста
|
||||
|
||||
prompt = f"""
|
||||
Ты — главный архитектор. Получена задача: {user_task}
|
||||
|
||||
Вот описание файлов проекта:
|
||||
{summaries_text}
|
||||
|
||||
При выполнении теста были обнаружены следующие ошибки:
|
||||
{errors_text}
|
||||
|
||||
Проанализируй ошибки. Определи, какие изменения в коде нужно внести, чтобы их исправить.
|
||||
Составь список задач для кодера (тип "code") с конкретными инструкциями по исправлению.
|
||||
Если ошибки связаны с отсутствием файлов или неправильными путями, добавь задачу по созданию или перемещению.
|
||||
Ответ дай строго в формате JSON-списка объектов: [{{"type": "code", "description": "описание"}}]
|
||||
Никаких пояснений, только JSON.
|
||||
"""
|
||||
messages = [{"role": "system", "content": "Ты — архитектор, выдаёшь только JSON."},
|
||||
{"role": "user", "content": prompt}]
|
||||
response = project.ollama_client.chat(messages, temperature=0.3)
|
||||
try:
|
||||
start = response.find('[')
|
||||
end = response.rfind(']') + 1
|
||||
if start != -1 and end != -1:
|
||||
json_str = response[start:end]
|
||||
tasks = json.loads(json_str)
|
||||
if isinstance(tasks, list) and all(
|
||||
isinstance(item, dict) and "type" in item and "description" in item for item in tasks):
|
||||
return tasks
|
||||
except Exception:
|
||||
pass
|
||||
return [{"type": "code", "description": "Исправить ошибки в коде (ручное вмешательство)"}]
|
||||
|
||||
@staticmethod
|
||||
def next_task(project: Project, user_task: str) -> dict:
|
||||
summaries = project.state.get("file_summaries", {})
|
||||
if not summaries:
|
||||
return {"type": "error", "description": "Нет описаний файлов"}
|
||||
|
||||
completed = project.state.get("completed", [])
|
||||
last_errors = project.state.get("last_errors", [])
|
||||
|
||||
errors_text = ""
|
||||
if last_errors:
|
||||
for err in last_errors[:5]:
|
||||
msg = err.get("message", "")
|
||||
loc = err.get("location")
|
||||
if loc:
|
||||
file_name = loc.get("url", "неизвестный файл")
|
||||
line = loc.get("line", "?")
|
||||
col = loc.get("column", "?")
|
||||
errors_text += f"- {msg} (в {file_name}:{line}:{col})\n"
|
||||
else:
|
||||
errors_text += f"- {msg}\n"
|
||||
if err.get("stack"):
|
||||
errors_text += f" Стек: {err['stack']}\n"
|
||||
else:
|
||||
errors_text = "Ошибок не зафиксировано."
|
||||
|
||||
summaries_text = "\n".join([f"- {path}: {desc}" for path, desc in list(summaries.items())[:10]])
|
||||
completed_text = "\n".join([f"- {task['type']}: {task['description']}" for task in completed]) or "нет"
|
||||
|
||||
prompt = f"""
|
||||
Ты — главный архитектор. Получена задача: {user_task}
|
||||
|
||||
Описание файлов проекта:
|
||||
{summaries_text}
|
||||
|
||||
Уже выполненные задачи:
|
||||
{completed_text}
|
||||
|
||||
Актуальные ошибки (с указанием файлов и строк):
|
||||
{errors_text}
|
||||
|
||||
Твоя задача — решить, что делать дальше.
|
||||
ВНИМАНИЕ: НЕ возвращай finish, пока не будут выполнены как минимум 2 задачи и не будет ошибок.
|
||||
Если ошибки есть — ты должен предложить задачу типа "code" для их исправления.
|
||||
Если ошибок нет и уже было выполнено хотя бы 2 задачи, тогда можешь вернуть finish.
|
||||
Иначе верни одну задачу для следующего шага. Типы задач:
|
||||
- "test" — запустить браузер и проверить консоль на ошибки (это нужно делать, если неизвестно состояние)
|
||||
- "code" — написать или изменить код. Укажи поле "files" — массив относительных путей к файлам, которые нужно передать кодеру. Старайся указывать файлы на основе информации об ошибках.
|
||||
- "browser" — открыть браузер для визуальной проверки
|
||||
|
||||
Ответ дай строго в формате JSON-объекта:
|
||||
{{"type": "test", "description": "описание"}}
|
||||
или
|
||||
{{"type": "code", "description": "описание", "files": ["путь/к/файлу"]}}
|
||||
Никаких пояснений, только JSON.
|
||||
"""
|
||||
messages = [{"role": "system", "content": "Ты — архитектор, выдаёшь только JSON."},
|
||||
{"role": "user", "content": prompt}]
|
||||
response = project.ollama_client.chat(messages, temperature=0.3)
|
||||
print(f"Ответ планировщика: {response}") # отладка
|
||||
|
||||
if not response:
|
||||
return {"type": "test", "description": "Проверить состояние"}
|
||||
|
||||
try:
|
||||
start = response.find('{')
|
||||
end = response.rfind('}') + 1
|
||||
if start != -1 and end != -1:
|
||||
json_str = response[start:end]
|
||||
task = json.loads(json_str)
|
||||
if "type" in task and "description" in task:
|
||||
if task["type"] == "code" and "files" not in task:
|
||||
task["files"] = []
|
||||
# Принудительно не даём finish, если мало задач выполнено
|
||||
if task.get("type") == "finish" and len(completed) < 2:
|
||||
return {"type": "test", "description": "Проверить состояние"}
|
||||
return task
|
||||
except Exception as e:
|
||||
print(f"Парсинг JSON не удался: {e}")
|
||||
|
||||
# Если не удалось распарсить, возвращаем тест по умолчанию
|
||||
return {"type": "test", "description": "Проверить состояние"}
|
||||
Reference in New Issue
Block a user