diff options
Diffstat (limited to 'continuedev/src')
4 files changed, 44 insertions, 33 deletions
| diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index 5a6bd2e7..97955ea2 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -26,6 +26,7 @@ class Autopilot(ContinueBaseModel):      _main_user_input_queue: List[str] = []      _user_input_queue = AsyncSubscriptionQueue() +    _retry_queue = AsyncSubscriptionQueue()      @property      def continue_sdk(self) -> ContinueSDK: @@ -83,9 +84,7 @@ class Autopilot(ContinueBaseModel):      _step_depth: int = 0      async def retry_at_index(self, index: int): -        step = self.history.timeline[index].step.copy() -        await self.update_subscribers() -        await self._run_singular_step(step) +        self._retry_queue.post(str(index), None)      async def _run_singular_step(self, step: "Step", is_future_step: bool = False) -> Coroutine[Observation, None, None]:          capture_event( @@ -109,50 +108,62 @@ class Autopilot(ContinueBaseModel):          # Try to run step and handle errors          self._step_depth += 1 +        caught_error = False          try:              observation = await step(self.continue_sdk) -        except ContinueCustomException as e: +        except Exception as e: +            caught_error = True + +            is_continue_custom_exception = issubclass( +                e.__class__, ContinueCustomException) + +            error_string = e.message if is_continue_custom_exception else '\n\n'.join( +                traceback.format_tb(e.__traceback__)) + f"\n\n{e.__repr__()}" +            error_title = e.title if is_continue_custom_exception else e.__repr__() +              # Attach an InternalErrorObservation to the step and unhide it. -            error_string = e.message -            print( -                f"\n{error_string}\n{e}") +            print(f"Error while running step: \n{error_string}\n{error_title}")              observation = InternalErrorObservation( -                error=error_string, title=e.title) +                error=error_string, title=error_title)              # Reveal this step, but hide all of the following steps (its substeps) +            step_was_hidden = step.hide +              step.hide = False              i = self.history.get_current_index()              while self.history.timeline[i].step.name != step.name:                  self.history.timeline[i].step.hide = True                  i -= 1 -            if e.with_step is not None: -                await self._run_singular_step(e.with_step) +            # i is now the index of the step that we want to show/rerun +            self.history.timeline[i].observation = observation -        except Exception as e: -            # Attach an InternalErrorObservation to the step and unhide it. -            error_string = '\n\n'.join( -                traceback.format_tb(e.__traceback__)) + f"\n\n{e.__repr__()}" -            print( -                f"Error while running step: \n{error_string}\n{e}") +            await self.update_subscribers() -            observation = InternalErrorObservation( -                error=error_string, title=e.__repr__()) +            # ContinueCustomException can optionally specify a step to run on the error +            if is_continue_custom_exception and e.with_step is not None: +                await self._run_singular_step(e.with_step) -            # Reveal this step, but hide all of the following steps (its substeps) -            step.hide = False -            i = self.history.get_current_index() -            while self.history.timeline[i].step.name != step.name: -                self.history.timeline[i].step.hide = True -                i -= 1 +            # Wait for a retry signal and then resume the step +            self._active = False +            await self._retry_queue.get(str(i)) +            self._active = True +            # You might consider a "ignore and continue" button +            # want it to have same step depth, so have to decrement +            self._step_depth -= 1 +            copy_step = step.copy() +            copy_step.hide = step_was_hidden +            observation = await self._run_singular_step(copy_step) +            self._step_depth += 1          self._step_depth -= 1 -        # Add observation to history -        self.history.get_last_at_depth( -            self._step_depth, include_current=True).observation = observation -        await self.update_subscribers() +        # Add observation to history, unless already attached error observation +        if not caught_error: +            self.history.get_last_at_depth( +                self._step_depth, include_current=True).observation = observation +            await self.update_subscribers()          # Update its description          if step.description is None: diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py index 51faadf2..d1f731da 100644 --- a/continuedev/src/continuedev/core/sdk.py +++ b/continuedev/src/continuedev/core/sdk.py @@ -86,7 +86,7 @@ class ContinueSDK(AbstractContinueSDK):          await self.ide.setFileOpen(filepath)          contents = await self.ide.readFile(filepath)          await self.run_step(Gpt35EditCodeStep( -            range_in_files=[RangeInFile(filepath=filename, range=range) if range is not None else RangeInFile.from_entire_file( +            range_in_files=[RangeInFile(filepath=filepath, range=range) if range is not None else RangeInFile.from_entire_file(                  filepath, contents)],              user_input=prompt,              description=description, diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py index 8c4ed8f7..6a2f4aed 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py @@ -89,7 +89,7 @@ class ValidatePipelineStep(Step):          output = await sdk.run(f'python3 {filename}', name="Test the pipeline", description=f"Running `python3 {filename}` to test loading data from the API")          # If it fails, return the error -        if "Traceback" in output: +        if "Traceback" in output or "SyntaxError" in output:              output = "Traceback" + output.split("Traceback")[-1]              file_content = await sdk.ide.readFile(os.path.join(workspace_dir, filename))              suggestion = (await sdk.models.gpt35()).complete(dedent(f"""\ diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 413bc195..250ced8b 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -100,7 +100,7 @@ class Gpt35EditCodeStep(Step):              return a + b          <|endoftext|> -        Now complete the real thing: +        Now complete the real thing. Do NOT rewrite the prefix or suffix.          <file_prefix>          {file_prefix} @@ -110,7 +110,8 @@ class Gpt35EditCodeStep(Step):          {code}          <commit_msg>          {user_request} -        <commit_after>""") +        <commit_after> +        """)      _prompt_and_completion: str = "" @@ -242,5 +243,4 @@ class WaitForUserConfirmationStep(Step):      async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]:          self.description = self.prompt          resp = await sdk.wait_for_user_input() -        self.hide = True          return TextObservation(text=resp) | 
