Repository: Pythagora-io/gpt-pilot
File: core/agents/troubleshooter.py (Python)

Code before:
        If "should_iterate" is False, the user has confirmed that the app works as expected and there's
        nothing for the troubleshooter or problem solver to do.

        If "is_loop" is True, Pythagora is stuck in a loop and needs to consider alternative solutions.

        The last element in the tuple is the user feedback, which may be empty if the user provided no
        feedback (eg. if they just clicked on "Continue" or "I'm stuck in a loop").
        """

        test_message = "Can you check if the app works please?"
        if user_instructions:
            hint = " Here is a description of what should be working:\n\n" + user_instructions

        if run_command:
            await self.ui.send_run_command(run_command)

        buttons = {"continue": "continue"}
        if last_iteration:
            buttons["loop"] = "I'm stuck in a loop"

        user_response = await self.ask_question(test_message, buttons=buttons, default="continue", hint=hint)
        if user_response.button == "continue" or user_response.cancelled:
            return False, False, ""

        if user_response.button == "loop":
            await telemetry.trace_code_event("stuck-in-loop", {"clicked": True})
            return True, True, ""

        return True, False, user_response.text

    def try_next_alternative_solution(self, user_feedback: str, user_feedback_qa: list[str]) -> AgentResponse:
        """
        Call the ProblemSolver to try an alternative solution.

        Stores the user feedback and sets iteration state (not completed, no description)
        so that ProblemSolver will be triggered.

        :param user_feedback: User feedback to store in the iteration state.
        :param user_feedback_qa: Additional questions/answers about the problem.
        :return: Agent response done.
        """
        next_state_iteration = self.next_state.iterations[-1]
        next_state_iteration["description"] = ""
        next_state_iteration["user_feedback"] = user_feedback
        next_state_iteration["user_feedback_qa"] = user_feedback_qa
        next_state_iteration["attempts"] += 1
        next_state_iteration["completed"] = False
        self.next_state.flag_iterations_as_modified()
        self.next_state.action = f"Alternative solution (attempt #{next_state_iteration['attempts']})"
        return AgentResponse.done(self)


Review comment (suggestion):
add:
- number of epics (is it the initial app or feature?)
- number of all tasks (is it the last task? Could be that we have most iterations on the last task because everyone clicks "continue" until it is the last task)
- current task index
- some data so we can find and analyze the db
- number of iterations
- number of steps
- tech stack? Then we can see easily on which stack is this button used the most

Code after:
        If "should_iterate" is False, the user has confirmed that the app works as expected and there's
        nothing for the troubleshooter or problem solver to do.

        If "is_loop" is True, Pythagora is stuck in a loop and needs to consider alternative solutions.

        The last element in the tuple is the user feedback, which may be empty if the user provided no
        feedback (eg. if they just clicked on "Continue" or "I'm stuck in a loop").
        """

        test_message = "Can you check if the app works please?"
        if user_instructions:
            hint = " Here is a description of what should be working:\n\n" + user_instructions

        if run_command:
            await self.ui.send_run_command(run_command)

        buttons = {"continue": "continue"}
        if last_iteration:
            buttons["loop"] = "I'm stuck in a loop"

        user_response = await self.ask_question(test_message, buttons=buttons, default="continue", hint=hint)
        if user_response.button == "continue" or user_response.cancelled:
            return False, False, ""

        if user_response.button == "loop":
            await telemetry.trace_code_event(
                "stuck-in-loop",
                {
                    "clicked": True,
                    "task_index": self.current_state.tasks.index(self.current_state.current_task) + 1,
                    "num_tasks": len(self.current_state.tasks),
                    "num_epics": len(self.current_state.epics),
                    "num_iterations": len(self.current_state.iterations),
                    "num_steps": len(self.current_state.steps),
                    "architecture": {
                        "system_dependencies": self.current_state.specification.system_dependencies,
                        "app_dependencies": self.current_state.specification.package_dependencies,
                    },
                },
            )
            return True, True, ""

        return True, False, user_response.text

    def try_next_alternative_solution(self, user_feedback: str, user_feedback_qa: list[str]) -> AgentResponse:
        """
        Call the ProblemSolver to try an alternative solution.

        Stores the user feedback and sets iteration state (not completed, no description)
        so that ProblemSolver will be triggered.