#nodes.py from app.agents.pm_agent import run_pm_agent from app.agents.dev_agent import run_dev_agent from app.agents.qa_agent import run_qa_agent from app.services.retrieval_service import find_existing_project from app.graph.state import WorkflowState from langchain_core.runnables import RunnableConfig async def pm_node(state: WorkflowState): history = state.get("chat_history", []) or [] if state.get("status") == "spec_incomplete" and state.get("user_feedback"): current_input = state["user_feedback"] full_user_input = f"{state['user_input']}\n{current_input}" else: current_input = state["user_input"] full_user_input = current_input spec = await run_pm_agent(user_input=current_input, history=history) updated_history = list(history) updated_history.append({"role": "user", "content": current_input}) if not spec.is_complete and spec.clarifying_question: updated_history.append({"role": "assistant", "content": spec.clarifying_question}) return { "spec": spec.model_dump(), "status": "spec_ready" if spec.is_complete else "spec_incomplete", "chat_history": updated_history, "user_input": full_user_input, "user_feedback": None, "loop_count": 0, } async def retrieval_node(state: WorkflowState, config: RunnableConfig): qdrant_repo = config.get("configurable", {}).get("qdrant_repo") if not qdrant_repo: raise ValueError("❌ Erreur : Le repository Qdrant n'a pas été transmis au graphe.") existing_project = await find_existing_project(qdrant_repo, state["user_input"]) return { "existing_project": existing_project, "status": "existing_found" if existing_project else "no_existing_project", } async def dev_node(state: WorkflowState): qa_logs = state.get("qa_result", {}).get("logs", "") if state.get("qa_result") else None generated_code = await run_dev_agent(state["spec"], qa_feedback=qa_logs) return { "generated_code": generated_code, "status": "code_generated", } async def qa_node(state: WorkflowState): qa_result = await run_qa_agent(state["generated_code"]) current_loops = state.get("loop_count", 0) is_success = True clean_qa_result = {"success": is_success, "raw": qa_result} return { "qa_result": clean_qa_result, "loop_count": current_loops if is_success else current_loops + 1, "status": "qa_done", } async def human_review_node(state: WorkflowState): print("[Human Review] Passage en mode automatique (Mock)...") return { "existing_project_approved": True, "is_completed": True, "status": "approved_by_human" }