80 lines
3.3 KiB
Python
80 lines
3.3 KiB
Python
from langgraph.graph import END, START, StateGraph
|
|
|
|
from app.modules.agent.engine.graphs.progress import emit_progress_sync
|
|
from app.modules.agent.engine.graphs.project_edits_logic import ProjectEditsLogic
|
|
from app.modules.agent.engine.graphs.state import AgentGraphState
|
|
from app.modules.agent.llm import AgentLlmService
|
|
|
|
|
|
class ProjectEditsGraphFactory:
|
|
_max_validation_attempts = 2
|
|
|
|
def __init__(self, llm: AgentLlmService) -> None:
|
|
self._logic = ProjectEditsLogic(llm)
|
|
|
|
def build(self, checkpointer=None):
|
|
graph = StateGraph(AgentGraphState)
|
|
graph.add_node("collect_context", self._collect_context)
|
|
graph.add_node("plan_changes", self._plan_changes)
|
|
graph.add_node("generate_changeset", self._generate_changeset)
|
|
graph.add_node("self_check", self._self_check)
|
|
graph.add_node("build_result", self._build_result)
|
|
|
|
graph.add_edge(START, "collect_context")
|
|
graph.add_edge("collect_context", "plan_changes")
|
|
graph.add_edge("plan_changes", "generate_changeset")
|
|
graph.add_edge("generate_changeset", "self_check")
|
|
graph.add_conditional_edges(
|
|
"self_check",
|
|
self._route_after_self_check,
|
|
{"retry": "generate_changeset", "ready": "build_result"},
|
|
)
|
|
graph.add_edge("build_result", END)
|
|
return graph.compile(checkpointer=checkpointer)
|
|
|
|
def _collect_context(self, state: AgentGraphState) -> dict:
|
|
emit_progress_sync(
|
|
state,
|
|
stage="graph.project_edits.collect_context",
|
|
message="Собираю контекст и релевантные файлы для правок.",
|
|
)
|
|
return self._logic.collect_context(state)
|
|
|
|
def _plan_changes(self, state: AgentGraphState) -> dict:
|
|
emit_progress_sync(
|
|
state,
|
|
stage="graph.project_edits.plan_changes",
|
|
message="Определяю, что именно нужно изменить и в каких файлах.",
|
|
)
|
|
return self._logic.plan_changes(state)
|
|
|
|
def _generate_changeset(self, state: AgentGraphState) -> dict:
|
|
emit_progress_sync(
|
|
state,
|
|
stage="graph.project_edits.generate_changeset",
|
|
message="Формирую предлагаемые правки по выбранным файлам.",
|
|
)
|
|
return self._logic.generate_changeset(state)
|
|
|
|
def _self_check(self, state: AgentGraphState) -> dict:
|
|
emit_progress_sync(
|
|
state,
|
|
stage="graph.project_edits.self_check",
|
|
message="Проверяю, что правки соответствуют запросу и не трогают лишнее.",
|
|
)
|
|
return self._logic.self_check(state)
|
|
|
|
def _build_result(self, state: AgentGraphState) -> dict:
|
|
emit_progress_sync(
|
|
state,
|
|
stage="graph.project_edits.build_result",
|
|
message="Формирую итоговый changeset и краткий обзор.",
|
|
)
|
|
return self._logic.build_result(state)
|
|
|
|
def _route_after_self_check(self, state: AgentGraphState) -> str:
|
|
if state.get("validation_passed"):
|
|
return "ready"
|
|
attempts = int(state.get("validation_attempts", 0) or 0)
|
|
return "ready" if attempts >= self._max_validation_attempts else "retry"
|