From 393eb93545567b9a3d1b6cd60a69e88bc15cf28c Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Sat, 27 May 2023 14:47:33 -0400 Subject: Refactoring and shortcut functions to common steps --- continuedev/src/continuedev/core/agent.py | 180 +++++++++++++++++++++ continuedev/src/continuedev/core/env.py | 7 + continuedev/src/continuedev/core/main.py | 148 +++++++++++++++++ continuedev/src/continuedev/core/observation.py | 35 ++++ continuedev/src/continuedev/core/policy.py | 93 +++++++++++ continuedev/src/continuedev/core/sdk.py | 62 +++++++ continuedev/src/continuedev/libs/agent.py | 180 --------------------- continuedev/src/continuedev/libs/core.py | 148 ----------------- continuedev/src/continuedev/libs/env.py | 7 - continuedev/src/continuedev/libs/observation.py | 35 ---- continuedev/src/continuedev/libs/policy.py | 91 ----------- continuedev/src/continuedev/libs/sdk.py | 39 ----- continuedev/src/continuedev/libs/steps/chroma.py | 9 +- .../src/continuedev/libs/steps/core/core.py | 133 ++++++++++++++- .../libs/steps/draft/abstract_method.py | 3 +- .../src/continuedev/libs/steps/draft/dlt.py | 3 +- .../src/continuedev/libs/steps/draft/redux.py | 7 +- .../src/continuedev/libs/steps/draft/typeorm.py | 3 +- continuedev/src/continuedev/libs/steps/main.py | 174 +++----------------- .../src/continuedev/libs/steps/migration.py | 2 +- continuedev/src/continuedev/libs/steps/nate.py | 9 +- continuedev/src/continuedev/libs/steps/pytest.py | 2 +- continuedev/src/continuedev/libs/steps/ty.py | 8 +- .../continuedev/plugins/policy/libs/alternate.py | 4 +- .../src/continuedev/plugins/step/hookspecs.py | 4 +- continuedev/src/continuedev/server/notebook.py | 10 +- 26 files changed, 713 insertions(+), 683 deletions(-) create mode 100644 continuedev/src/continuedev/core/agent.py create mode 100644 continuedev/src/continuedev/core/env.py create mode 100644 continuedev/src/continuedev/core/main.py create mode 100644 continuedev/src/continuedev/core/observation.py create mode 100644 continuedev/src/continuedev/core/policy.py create mode 100644 continuedev/src/continuedev/core/sdk.py delete mode 100644 continuedev/src/continuedev/libs/agent.py delete mode 100644 continuedev/src/continuedev/libs/core.py delete mode 100644 continuedev/src/continuedev/libs/env.py delete mode 100644 continuedev/src/continuedev/libs/observation.py delete mode 100644 continuedev/src/continuedev/libs/policy.py delete mode 100644 continuedev/src/continuedev/libs/sdk.py (limited to 'continuedev/src') diff --git a/continuedev/src/continuedev/core/agent.py b/continuedev/src/continuedev/core/agent.py new file mode 100644 index 00000000..509a54b3 --- /dev/null +++ b/continuedev/src/continuedev/core/agent.py @@ -0,0 +1,180 @@ +import traceback +import time +from typing import Callable, Coroutine, List +from ..models.filesystem_edit import FileEditWithFullContents +from ..libs.llm import LLM +from .observation import Observation +from ..server.ide_protocol import AbstractIdeProtocolServer +from ..libs.util.queue import AsyncSubscriptionQueue +from ..models.main import ContinueBaseModel +from .main import Policy, History, FullState, Step, HistoryNode +from ..libs.steps.core.core import ReversibleStep, ManualEditStep, UserInputStep +from .sdk import ContinueSDK + + +class Agent(ContinueBaseModel): + llm: LLM + policy: Policy + ide: AbstractIdeProtocolServer + history: History = History.from_empty() + continue_sdk: "ContinueSDK" + _on_update_callbacks: List[Callable[[FullState], None]] = [] + + _active: bool = False + _should_halt: bool = False + _main_user_input_queue: List[str] = [] + + _user_input_queue = AsyncSubscriptionQueue() + + class Config: + arbitrary_types_allowed = True + + def get_full_state(self) -> FullState: + return FullState(history=self.history, active=self._active, user_input_queue=self._main_user_input_queue) + + def on_update(self, callback: Callable[["FullState"], None]): + """Subscribe to changes to state""" + self._on_update_callbacks.append(callback) + + def update_subscribers(self): + full_state = self.get_full_state() + for callback in self._on_update_callbacks: + callback(full_state) + + def __get_step_params(self, step: "Step"): + return ContinueSDK(agent=self, llm=self.llm.with_system_message(step.system_message)) + + def give_user_input(self, input: str, index: int): + self._user_input_queue.post(index, input) + + async def wait_for_user_input(self) -> str: + self._active = False + self.update_subscribers() + await self._user_input_queue.get(self.history.current_index) + self._active = True + self.update_subscribers() + + _manual_edits_buffer: List[FileEditWithFullContents] = [] + + async def reverse_to_index(self, index: int): + try: + while self.history.get_current_index() >= index: + current_step = self.history.get_current().step + self.history.step_back() + if issubclass(current_step.__class__, ReversibleStep): + await current_step.reverse(self.__get_step_params(current_step)) + + self.update_subscribers() + except Exception as e: + print(e) + + def handle_manual_edits(self, edits: List[FileEditWithFullContents]): + for edit in edits: + self._manual_edits_buffer.append(edit) + # TODO: You're storing a lot of unecessary data here. Can compress into EditDiffs on the spot, and merge. + # self._manual_edits_buffer = merge_file_edit(self._manual_edits_buffer, edit) + + def handle_traceback(self, traceback: str): + raise NotImplementedError + + _step_depth: int = 0 + + async def _run_singular_step(self, step: "Step", is_future_step: bool = False) -> Coroutine[Observation, None, None]: + if not is_future_step: + # Check manual edits buffer, clear out if needed by creating a ManualEditStep + if len(self._manual_edits_buffer) > 0: + manualEditsStep = ManualEditStep.from_sequence( + self._manual_edits_buffer) + self._manual_edits_buffer = [] + await self._run_singular_step(manualEditsStep) + + # Update history - do this first so we get top-first tree ordering + self.history.add_node(HistoryNode( + step=step, observation=None, depth=self._step_depth)) + + # Run step + self._step_depth += 1 + observation = await step(self.__get_step_params(step)) + self._step_depth -= 1 + + # Add observation to history + self.history.get_current().observation = observation + + # Update its description + step._set_description(await step.describe(self.llm)) + + # Call all subscribed callbacks + self.update_subscribers() + + return observation + + async def run_from_step(self, step: "Step"): + # if self._active: + # raise RuntimeError("Agent is already running") + self._active = True + + next_step = step + is_future_step = False + while not (next_step is None or self._should_halt): + try: + if is_future_step: + # If future step, then we are replaying and need to delete the step from history so it can be replaced + self.history.remove_current_and_substeps() + + observation = await self._run_singular_step(next_step, is_future_step) + if next_step := self.policy.next(self.history): + is_future_step = False + elif next_step := self.history.take_next_step(): + is_future_step = True + else: + next_step = None + + except Exception as e: + print( + f"Error while running step: \n{''.join(traceback.format_tb(e.__traceback__))}\n{e}") + next_step = None + + self._active = False + + # Doing this so active can make it to the frontend after steps are done. But want better state syncing tools + for callback in self._on_update_callbacks: + callback(None) + + async def run_from_observation(self, observation: Observation): + next_step = self.policy.next(self.history) + await self.run_from_step(next_step) + + async def run_policy(self): + first_step = self.policy.next(self.history) + await self.run_from_step(first_step) + + async def _request_halt(self): + if self._active: + self._should_halt = True + while self._active: + time.sleep(0.1) + self._should_halt = False + return None + + async def accept_user_input(self, user_input: str): + self._main_user_input_queue.append(user_input) + self.update_subscribers() + + if len(self._main_user_input_queue) > 1: + return + + # await self._request_halt() + # Just run the step that takes user input, and + # then up to the policy to decide how to deal with it. + self._main_user_input_queue.pop(0) + self.update_subscribers() + await self.run_from_step(UserInputStep(user_input=user_input)) + + while len(self._main_user_input_queue) > 0: + await self.run_from_step(UserInputStep( + user_input=self._main_user_input_queue.pop(0))) + + async def accept_refinement_input(self, user_input: str, index: int): + await self._request_halt() + await self.reverse_to_index(index) + await self.run_from_step(UserInputStep(user_input=user_input)) diff --git a/continuedev/src/continuedev/core/env.py b/continuedev/src/continuedev/core/env.py new file mode 100644 index 00000000..d7275b41 --- /dev/null +++ b/continuedev/src/continuedev/core/env.py @@ -0,0 +1,7 @@ +from dotenv import load_dotenv +import os + +load_dotenv() + + +openai_api_key = os.getenv("OPENAI_API_KEY") diff --git a/continuedev/src/continuedev/core/main.py b/continuedev/src/continuedev/core/main.py new file mode 100644 index 00000000..51fcd299 --- /dev/null +++ b/continuedev/src/continuedev/core/main.py @@ -0,0 +1,148 @@ +from typing import Callable, Coroutine, Dict, Generator, List, Tuple, Union + +from ..models.main import ContinueBaseModel +from pydantic import validator +from ..libs.llm import LLM +from .observation import Observation + + +class HistoryNode(ContinueBaseModel): + """A point in history, a list of which make up History""" + step: "Step" + observation: Union[Observation, None] + depth: int + + +class History(ContinueBaseModel): + """A history of steps taken and their results""" + timeline: List[HistoryNode] + current_index: int + + def add_node(self, node: HistoryNode): + self.timeline.insert(self.current_index + 1, node) + self.current_index += 1 + + def get_current(self) -> Union[HistoryNode, None]: + if self.current_index < 0: + return None + return self.timeline[self.current_index] + + def remove_current_and_substeps(self): + self.timeline.pop(self.current_index) + while self.get_current() is not None and self.get_current().depth > 0: + self.timeline.pop(self.current_index) + + def take_next_step(self) -> Union["Step", None]: + if self.has_future(): + self.current_index += 1 + current_state = self.get_current() + if current_state is None: + return None + return current_state.step + return None + + def get_current_index(self) -> int: + return self.current_index + + def has_future(self) -> bool: + return self.current_index < len(self.timeline) - 1 + + def step_back(self): + self.current_index -= 1 + + def last_observation(self) -> Union[Observation, None]: + state = self.get_current() + if state is None: + return None + return state.observation + + @classmethod + def from_empty(cls): + return cls(timeline=[], current_index=-1) + + +class FullState(ContinueBaseModel): + """A full state of the program, including the history""" + history: History + active: bool + user_input_queue: List[str] + + +class ContinueSDK: + pass + + +class SequentialStep: + pass + + +class Policy(ContinueBaseModel): + """A rule that determines which step to take next""" + + # Note that history is mutable, kinda sus + def next(self, history: History = History.from_empty()) -> "Step": + raise NotImplementedError + + +class Step(ContinueBaseModel): + name: str = None + hide: bool = False + _description: Union[str, None] = None + + system_message: Union[str, None] = None + + class Config: + copy_on_model_validation = False + + async def describe(self, llm: LLM) -> Coroutine[str, None, None]: + if self._description is not None: + return self._description + return "Running step: " + self.name + + def _set_description(self, description: str): + self._description = description + + def dict(self, *args, **kwargs): + d = super().dict(*args, **kwargs) + if self._description is not None: + d["description"] = self._description + else: + d["description"] = self.name + return d + + @validator("name", pre=True, always=True) + def name_is_class_name(cls, name): + if name is None: + return cls.__name__ + return name + + async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: + raise NotImplementedError + + async def __call__(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: + return await self.run(sdk) + + def __rshift__(self, other: "Step"): + steps = [] + if isinstance(self, SequentialStep): + steps = self.steps + else: + steps.append(self) + if isinstance(other, SequentialStep): + steps += other.steps + else: + steps.append(other) + return SequentialStep(steps=steps) + + +class ValidatorObservation(Observation): + passed: bool + observation: Observation + + +class Validator(Step): + def run(self, sdk: ContinueSDK) -> ValidatorObservation: + raise NotImplementedError + + +HistoryNode.update_forward_refs() diff --git a/continuedev/src/continuedev/core/observation.py b/continuedev/src/continuedev/core/observation.py new file mode 100644 index 00000000..fef04311 --- /dev/null +++ b/continuedev/src/continuedev/core/observation.py @@ -0,0 +1,35 @@ +from pydantic import BaseModel, validator +from ..models.main import Traceback + + +class Observation(BaseModel): + pass + + +class TracebackObservation(Observation): + traceback: Traceback + + +class ValidatorObservation(Observation): + passed: bool + + +class UserInputObservation(Observation): + user_input: str + + +class DictObservation(Observation): + values: dict + + def __getitem__(self, key): + return self.values[key] + + +class TextObservation(Observation): + text: str + + @validator("text", pre=True, always=True) + def text_not_none(cls, v): + if v is None: + return "" + return v diff --git a/continuedev/src/continuedev/core/policy.py b/continuedev/src/continuedev/core/policy.py new file mode 100644 index 00000000..9e6abf14 --- /dev/null +++ b/continuedev/src/continuedev/core/policy.py @@ -0,0 +1,93 @@ +from typing import List, Tuple, Type + +from ..models.main import ContinueBaseModel + +from ..libs.steps.ty import CreatePipelineStep +from .main import Step, Validator, History, Policy +from .observation import Observation, TracebackObservation, UserInputObservation +from ..libs.steps.main import EditHighlightedCodeStep, SolveTracebackStep, RunCodeStep +from ..libs.steps.nate import WritePytestsStep, CreateTableStep +from ..libs.steps.chroma import AnswerQuestionChroma, EditFileChroma + + +class DemoPolicy(Policy): + ran_code_last: bool = False + cmd: str + + def next(self, history: History) -> Step: + observation = history.last_observation() + if observation is not None and isinstance(observation, UserInputObservation): + # This could be defined with ObservationTypePolicy. Ergonomics not right though. + if " test" in observation.user_input.lower(): + return WritePytestsStep(instructions=observation.user_input) + elif "/dlt" in observation.user_input.lower() or " dlt" in observation.user_input.lower(): + return CreatePipelineStep() + elif "/table" in observation.user_input: + return CreateTableStep(sql_str=" ".join(observation.user_input.split(" ")[1:])) + elif "/ask" in observation.user_input: + return AnswerQuestionChroma(question=" ".join(observation.user_input.split(" ")[1:])) + elif "/edit" in observation.user_input: + return EditFileChroma(request=" ".join(observation.user_input.split(" ")[1:])) + return EditHighlightedCodeStep(user_input=observation.user_input) + + state = history.get_current() + if state is None or not self.ran_code_last: + self.ran_code_last = True + return RunCodeStep(cmd=self.cmd) + + if observation is not None and isinstance(observation, TracebackObservation): + self.ran_code_last = False + return SolveTracebackStep(traceback=observation.traceback) + else: + return None + + +class ObservationTypePolicy(Policy): + def __init__(self, base_policy: Policy, observation_type: Type[Observation], step_type: Type[Step]): + self.observation_type = observation_type + self.step_type = step_type + self.base_policy = base_policy + + def next(self, history: History) -> Step: + observation = history.last_observation() + if observation is not None and isinstance(observation, self.observation_type): + return self.step_type(observation) + return self.base_policy.next(history) + + +class PolicyWrappedWithValidators(Policy): + """Default is to stop, unless the validator tells what to do next""" + index: int + stage: int + + def __init__(self, base_policy: Policy, pairs: List[Tuple[Validator, Type[Step]]]): + # Want to pass Type[Validator], or just the Validator? Question of where params are coming from. + self.pairs = pairs + self.index = len(pairs) + self.validating = 0 + self.base_policy = base_policy + + def next(self, history: History) -> Step: + if self.index == len(self.pairs): + self.index = 0 + return self.base_policy.next(history) + + if self.stage == 0: + # Running the validator at the current index for the first time + validator, step = self.pairs[self.index] + self.stage = 1 + return validator + elif self.stage == 1: + # Previously ran the validator at the current index, now receiving its ValidatorObservation + observation = history.last_observation() + if observation.passed: + self.stage = 0 + self.index += 1 + if self.index == len(self.pairs): + self.index = 0 + return self.base_policy.next(history) + else: + return self.pairs[self.index][0] + else: + _, step_type = self.pairs[self.index] + return step_type(observation) diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py new file mode 100644 index 00000000..ff62a2b1 --- /dev/null +++ b/continuedev/src/continuedev/core/sdk.py @@ -0,0 +1,62 @@ +from typing import Coroutine, Union +from ..models.filesystem_edit import FileSystemEdit +from ..models.filesystem import RangeInFile +from ..libs.llm import LLM +from .observation import Observation +from ..server.ide_protocol import AbstractIdeProtocolServer +from .main import History, Step +from ..libs.steps.core.core import * + + +class Agent: + pass + + +class ContinueSDKSteps: + def __init__(self, sdk: "ContinueSDK"): + self.sdk = sdk + + +class ContinueSDK: + """The SDK provided as parameters to a step""" + llm: LLM + ide: AbstractIdeProtocolServer + steps: ContinueSDKSteps + __agent: Agent + + def __init__(self, agent: Agent, llm: Union[LLM, None] = None): + if llm is None: + self.llm = agent.llm + else: + self.llm = llm + self.ide = agent.ide + self.__agent = agent + self.steps = ContinueSDKSteps(self) + + @property + def history(self) -> History: + return self.__agent.history + + async def run_step(self, step: Step) -> Coroutine[Observation, None, None]: + return await self.__agent._run_singular_step(step) + + async def apply_filesystem_edit(self, edit: FileSystemEdit): + await self.run_step(FileSystemEditStep(edit=edit)) + + async def wait_for_user_input(self) -> str: + return await self.__agent.wait_for_user_input() + + async def wait_for_user_confirmation(self, prompt: str): + return await self.run_step(WaitForUserConfirmationStep(prompt=prompt)) + + async def run(self, commands: List[str] | str, cwd: str = None): + commands = commands if isinstance(commands, List) else [commands] + return self.run_step(ShellCommandsStep(commands=commands, cwd=cwd)) + + async def edit_file(self, filename: str, prompt: str): + await self.ide.setFileOpen(filename) + contents = await self.ide.readFile(filename) + await self.run_step(EditCodeStep( + range_in_files=[RangeInFile.from_entire_file(filename, contents)], + prompt=f'Here is the code before:\n\n{{code}}\n\nHere is the user request:\n\n{prompt}\n\nHere is the code edited to perfectly solve the user request:\n\n' + )) diff --git a/continuedev/src/continuedev/libs/agent.py b/continuedev/src/continuedev/libs/agent.py deleted file mode 100644 index 466aa234..00000000 --- a/continuedev/src/continuedev/libs/agent.py +++ /dev/null @@ -1,180 +0,0 @@ -import traceback -import time -from typing import Callable, Coroutine, List -from ..models.filesystem_edit import FileEditWithFullContents -from .llm import LLM -from .observation import Observation -from ..server.ide_protocol import AbstractIdeProtocolServer -from .util.queue import AsyncSubscriptionQueue -from ..models.main import ContinueBaseModel -from .core import Policy, History, FullState, Step, HistoryNode -from .steps.core.core import ReversibleStep, ManualEditStep, UserInputStep -from .sdk import ContinueSDK - - -class Agent(ContinueBaseModel): - llm: LLM - policy: Policy - ide: AbstractIdeProtocolServer - history: History = History.from_empty() - continue_sdk: "ContinueSDK" - _on_update_callbacks: List[Callable[[FullState], None]] = [] - - _active: bool = False - _should_halt: bool = False - _main_user_input_queue: List[str] = [] - - _user_input_queue = AsyncSubscriptionQueue() - - class Config: - arbitrary_types_allowed = True - - def get_full_state(self) -> FullState: - return FullState(history=self.history, active=self._active, user_input_queue=self._main_user_input_queue) - - def on_update(self, callback: Callable[["FullState"], None]): - """Subscribe to changes to state""" - self._on_update_callbacks.append(callback) - - def update_subscribers(self): - full_state = self.get_full_state() - for callback in self._on_update_callbacks: - callback(full_state) - - def __get_step_params(self, step: "Step"): - return ContinueSDK(agent=self, llm=self.llm.with_system_message(step.system_message)) - - def give_user_input(self, input: str, index: int): - self._user_input_queue.post(index, input) - - async def wait_for_user_input(self) -> str: - self._active = False - self.update_subscribers() - await self._user_input_queue.get(self.history.current_index) - self._active = True - self.update_subscribers() - - _manual_edits_buffer: List[FileEditWithFullContents] = [] - - async def reverse_to_index(self, index: int): - try: - while self.history.get_current_index() >= index: - current_step = self.history.get_current().step - self.history.step_back() - if issubclass(current_step.__class__, ReversibleStep): - await current_step.reverse(self.__get_step_params(current_step)) - - self.update_subscribers() - except Exception as e: - print(e) - - def handle_manual_edits(self, edits: List[FileEditWithFullContents]): - for edit in edits: - self._manual_edits_buffer.append(edit) - # TODO: You're storing a lot of unecessary data here. Can compress into EditDiffs on the spot, and merge. - # self._manual_edits_buffer = merge_file_edit(self._manual_edits_buffer, edit) - - def handle_traceback(self, traceback: str): - raise NotImplementedError - - _step_depth: int = 0 - - async def _run_singular_step(self, step: "Step", is_future_step: bool = False) -> Coroutine[Observation, None, None]: - if not is_future_step: - # Check manual edits buffer, clear out if needed by creating a ManualEditStep - if len(self._manual_edits_buffer) > 0: - manualEditsStep = ManualEditStep.from_sequence( - self._manual_edits_buffer) - self._manual_edits_buffer = [] - await self._run_singular_step(manualEditsStep) - - # Update history - do this first so we get top-first tree ordering - self.history.add_node(HistoryNode( - step=step, observation=None, depth=self._step_depth)) - - # Run step - self._step_depth += 1 - observation = await step(self.__get_step_params(step)) - self._step_depth -= 1 - - # Add observation to history - self.history.get_current().observation = observation - - # Update its description - step._set_description(await step.describe(self.llm)) - - # Call all subscribed callbacks - self.update_subscribers() - - return observation - - async def run_from_step(self, step: "Step"): - # if self._active: - # raise RuntimeError("Agent is already running") - self._active = True - - next_step = step - is_future_step = False - while not (next_step is None or self._should_halt): - try: - if is_future_step: - # If future step, then we are replaying and need to delete the step from history so it can be replaced - self.history.remove_current_and_substeps() - - observation = await self._run_singular_step(next_step, is_future_step) - if next_step := self.policy.next(self.history): - is_future_step = False - elif next_step := self.history.take_next_step(): - is_future_step = True - else: - next_step = None - - except Exception as e: - print( - f"Error while running step: \n{''.join(traceback.format_tb(e.__traceback__))}\n{e}") - next_step = None - - self._active = False - - # Doing this so active can make it to the frontend after steps are done. But want better state syncing tools - for callback in self._on_update_callbacks: - callback(None) - - async def run_from_observation(self, observation: Observation): - next_step = self.policy.next(self.history) - await self.run_from_step(next_step) - - async def run_policy(self): - first_step = self.policy.next(self.history) - await self.run_from_step(first_step) - - async def _request_halt(self): - if self._active: - self._should_halt = True - while self._active: - time.sleep(0.1) - self._should_halt = False - return None - - async def accept_user_input(self, user_input: str): - self._main_user_input_queue.append(user_input) - self.update_subscribers() - - if len(self._main_user_input_queue) > 1: - return - - # await self._request_halt() - # Just run the step that takes user input, and - # then up to the policy to decide how to deal with it. - self._main_user_input_queue.pop(0) - self.update_subscribers() - await self.run_from_step(UserInputStep(user_input=user_input)) - - while len(self._main_user_input_queue) > 0: - await self.run_from_step(UserInputStep( - user_input=self._main_user_input_queue.pop(0))) - - async def accept_refinement_input(self, user_input: str, index: int): - await self._request_halt() - await self.reverse_to_index(index) - await self.run_from_step(UserInputStep(user_input=user_input)) diff --git a/continuedev/src/continuedev/libs/core.py b/continuedev/src/continuedev/libs/core.py deleted file mode 100644 index 9d432c4b..00000000 --- a/continuedev/src/continuedev/libs/core.py +++ /dev/null @@ -1,148 +0,0 @@ -from typing import Callable, Coroutine, Dict, Generator, List, Tuple, Union - -from ..models.main import ContinueBaseModel -from pydantic import validator -from .llm import LLM -from .observation import Observation - - -class HistoryNode(ContinueBaseModel): - """A point in history, a list of which make up History""" - step: "Step" - observation: Union[Observation, None] - depth: int - - -class History(ContinueBaseModel): - """A history of steps taken and their results""" - timeline: List[HistoryNode] - current_index: int - - def add_node(self, node: HistoryNode): - self.timeline.insert(self.current_index + 1, node) - self.current_index += 1 - - def get_current(self) -> Union[HistoryNode, None]: - if self.current_index < 0: - return None - return self.timeline[self.current_index] - - def remove_current_and_substeps(self): - self.timeline.pop(self.current_index) - while self.get_current() is not None and self.get_current().depth > 0: - self.timeline.pop(self.current_index) - - def take_next_step(self) -> Union["Step", None]: - if self.has_future(): - self.current_index += 1 - current_state = self.get_current() - if current_state is None: - return None - return current_state.step - return None - - def get_current_index(self) -> int: - return self.current_index - - def has_future(self) -> bool: - return self.current_index < len(self.timeline) - 1 - - def step_back(self): - self.current_index -= 1 - - def last_observation(self) -> Union[Observation, None]: - state = self.get_current() - if state is None: - return None - return state.observation - - @classmethod - def from_empty(cls): - return cls(timeline=[], current_index=-1) - - -class FullState(ContinueBaseModel): - """A full state of the program, including the history""" - history: History - active: bool - user_input_queue: List[str] - - -class Policy(ContinueBaseModel): - """A rule that determines which step to take next""" - - # Note that history is mutable, kinda sus - def next(self, history: History = History.from_empty()) -> "Step": - raise NotImplementedError - - -class ContinueSDK: - pass - - -class SequentialStep: - pass - - -class Step(ContinueBaseModel): - name: str = None - hide: bool = False - _description: Union[str, None] = None - - system_message: Union[str, None] = None - - class Config: - copy_on_model_validation = False - - async def describe(self, llm: LLM) -> Coroutine[str, None, None]: - if self._description is not None: - return self._description - return "Running step: " + self.name - - def _set_description(self, description: str): - self._description = description - - def dict(self, *args, **kwargs): - d = super().dict(*args, **kwargs) - if self._description is not None: - d["description"] = self._description - else: - d["description"] = self.name - return d - - @validator("name", pre=True, always=True) - def name_is_class_name(cls, name): - if name is None: - return cls.__name__ - return name - - async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - raise NotImplementedError - - async def __call__(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - return await self.run(sdk) - - def __rshift__(self, other: "Step"): - steps = [] - if isinstance(self, SequentialStep): - steps = self.steps - else: - steps.append(self) - if isinstance(other, SequentialStep): - steps += other.steps - else: - steps.append(other) - return SequentialStep(steps=steps) - - -class ValidatorObservation(Observation): - passed: bool - observation: Observation - - -class Validator(Step): - def run(self, sdk: ContinueSDK) -> ValidatorObservation: - raise NotImplementedError - - -HistoryNode.update_forward_refs() diff --git a/continuedev/src/continuedev/libs/env.py b/continuedev/src/continuedev/libs/env.py deleted file mode 100644 index d7275b41..00000000 --- a/continuedev/src/continuedev/libs/env.py +++ /dev/null @@ -1,7 +0,0 @@ -from dotenv import load_dotenv -import os - -load_dotenv() - - -openai_api_key = os.getenv("OPENAI_API_KEY") diff --git a/continuedev/src/continuedev/libs/observation.py b/continuedev/src/continuedev/libs/observation.py deleted file mode 100644 index fef04311..00000000 --- a/continuedev/src/continuedev/libs/observation.py +++ /dev/null @@ -1,35 +0,0 @@ -from pydantic import BaseModel, validator -from ..models.main import Traceback - - -class Observation(BaseModel): - pass - - -class TracebackObservation(Observation): - traceback: Traceback - - -class ValidatorObservation(Observation): - passed: bool - - -class UserInputObservation(Observation): - user_input: str - - -class DictObservation(Observation): - values: dict - - def __getitem__(self, key): - return self.values[key] - - -class TextObservation(Observation): - text: str - - @validator("text", pre=True, always=True) - def text_not_none(cls, v): - if v is None: - return "" - return v diff --git a/continuedev/src/continuedev/libs/policy.py b/continuedev/src/continuedev/libs/policy.py deleted file mode 100644 index 586eaebe..00000000 --- a/continuedev/src/continuedev/libs/policy.py +++ /dev/null @@ -1,91 +0,0 @@ -from typing import List, Tuple, Type - -from .steps.ty import CreatePipelineStep -from .core import Step, Validator, Policy, History -from .observation import Observation, TracebackObservation, UserInputObservation -from .steps.main import EditCodeStep, EditHighlightedCodeStep, SolveTracebackStep, RunCodeStep, FasterEditHighlightedCodeStep -from .steps.nate import WritePytestsStep, CreateTableStep -from .steps.chroma import AnswerQuestionChroma, EditFileChroma - - -class DemoPolicy(Policy): - ran_code_last: bool = False - cmd: str - - def next(self, history: History) -> Step: - observation = history.last_observation() - if observation is not None and isinstance(observation, UserInputObservation): - # This could be defined with ObservationTypePolicy. Ergonomics not right though. - if " test" in observation.user_input.lower(): - return WritePytestsStep(instructions=observation.user_input) - elif "/dlt" in observation.user_input.lower() or " dlt" in observation.user_input.lower(): - return CreatePipelineStep() - elif "/table" in observation.user_input: - return CreateTableStep(sql_str=" ".join(observation.user_input.split(" ")[1:])) - elif "/ask" in observation.user_input: - return AnswerQuestionChroma(question=" ".join(observation.user_input.split(" ")[1:])) - elif "/edit" in observation.user_input: - return EditFileChroma(request=" ".join(observation.user_input.split(" ")[1:])) - return EditHighlightedCodeStep(user_input=observation.user_input) - - state = history.get_current() - if state is None or not self.ran_code_last: - self.ran_code_last = True - return RunCodeStep(cmd=self.cmd) - - if observation is not None and isinstance(observation, TracebackObservation): - self.ran_code_last = False - return SolveTracebackStep(traceback=observation.traceback) - else: - return None - - -class ObservationTypePolicy(Policy): - def __init__(self, base_policy: Policy, observation_type: Type[Observation], step_type: Type[Step]): - self.observation_type = observation_type - self.step_type = step_type - self.base_policy = base_policy - - def next(self, history: History) -> Step: - observation = history.last_observation() - if observation is not None and isinstance(observation, self.observation_type): - return self.step_type(observation) - return self.base_policy.next(history) - - -class PolicyWrappedWithValidators(Policy): - """Default is to stop, unless the validator tells what to do next""" - index: int - stage: int - - def __init__(self, base_policy: Policy, pairs: List[Tuple[Validator, Type[Step]]]): - # Want to pass Type[Validator], or just the Validator? Question of where params are coming from. - self.pairs = pairs - self.index = len(pairs) - self.validating = 0 - self.base_policy = base_policy - - def next(self, history: History) -> Step: - if self.index == len(self.pairs): - self.index = 0 - return self.base_policy.next(history) - - if self.stage == 0: - # Running the validator at the current index for the first time - validator, step = self.pairs[self.index] - self.stage = 1 - return validator - elif self.stage == 1: - # Previously ran the validator at the current index, now receiving its ValidatorObservation - observation = history.last_observation() - if observation.passed: - self.stage = 0 - self.index += 1 - if self.index == len(self.pairs): - self.index = 0 - return self.base_policy.next(history) - else: - return self.pairs[self.index][0] - else: - _, step_type = self.pairs[self.index] - return step_type(observation) diff --git a/continuedev/src/continuedev/libs/sdk.py b/continuedev/src/continuedev/libs/sdk.py deleted file mode 100644 index 0295bf35..00000000 --- a/continuedev/src/continuedev/libs/sdk.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import Coroutine, Union -from ..models.filesystem_edit import FileSystemEdit -from .llm import LLM -from .observation import Observation -from ..server.ide_protocol import AbstractIdeProtocolServer -from .core import History, Step -from .steps.core.core import * - - -class Agent: - pass - - -class ContinueSDK: - """The SDK provided as parameters to a step""" - llm: LLM - ide: AbstractIdeProtocolServer - __agent: Agent - - def __init__(self, agent: Agent, llm: Union[LLM, None] = None): - if llm is None: - self.llm = agent.llm - else: - self.llm = llm - self.ide = agent.ide - self.__agent = agent - - @property - def history(self) -> History: - return self.__agent.history - - async def run_step(self, step: Step) -> Coroutine[Observation, None, None]: - return await self.__agent._run_singular_step(step) - - async def apply_filesystem_edit(self, edit: FileSystemEdit): - await self.run_step(FileSystemEditStep(edit=edit)) - - async def wait_for_user_input(self) -> str: - return await self.__agent.wait_for_user_input() diff --git a/continuedev/src/continuedev/libs/steps/chroma.py b/continuedev/src/continuedev/libs/steps/chroma.py index 2d8742e8..f13a2bab 100644 --- a/continuedev/src/continuedev/libs/steps/chroma.py +++ b/continuedev/src/continuedev/libs/steps/chroma.py @@ -1,11 +1,10 @@ from textwrap import dedent from typing import Coroutine, Union -from ...models.filesystem_edit import AddDirectory, AddFile -from ..observation import Observation, TextObservation -from ..core import Step, ContinueSDK -from .main import EditCodeStep, EditFileStep, RunCommandStep, WaitForUserConfirmationStep +from ...core.observation import Observation, TextObservation +from ...core.main import Step, ContinueSDK +from .core.core import EditFileStep from ..chroma.query import query_codebase_index -from .main import EditFileStep +from .core.core import EditFileStep class AnswerQuestionChroma(Step): diff --git a/continuedev/src/continuedev/libs/steps/core/core.py b/continuedev/src/continuedev/libs/steps/core/core.py index 23086b53..0338d635 100644 --- a/continuedev/src/continuedev/libs/steps/core/core.py +++ b/continuedev/src/continuedev/libs/steps/core/core.py @@ -1,11 +1,16 @@ # These steps are depended upon by ContinueSDK -from typing import Callable, Coroutine, Dict, Generator, List, Tuple, Union +import subprocess +from textwrap import dedent +from typing import Coroutine, List, Union +from ...llm.prompt_utils import MarkdownStyleEncoderDecoder + +from ...util.traceback_parsers import parse_python_traceback from ....models.filesystem_edit import EditDiff, FileEditWithFullContents, FileSystemEdit -from ....models.filesystem import FileSystem +from ....models.filesystem import FileSystem, RangeInFile, RangeInFileWithContents from ...llm import LLM -from ...observation import Observation, UserInputObservation -from ...core import Step +from ....core.observation import Observation, TextObservation, TracebackObservation, UserInputObservation +from ....core.main import Step class ContinueSDK: @@ -42,6 +47,98 @@ class FileSystemEditStep(ReversibleStep): # Where and when should file saves happen? +def ShellCommandsStep(Step): + cmds: List[str] + cwd: str | None = None + name: str = "Run Shell Commands" + + async def describe(self, llm: LLM) -> Coroutine[str, None, None]: + return "\n".join(self.cmds) + + async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: + cwd = await sdk.ide.getWorkspaceDirectory() if self.cwd is None else self.cwd + + process = subprocess.Popen( + '/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=cwd) + + stdin_input = "\n".join(self.cmds) + out, err = process.communicate(stdin_input.encode()) + + # If it fails, return the error + if err is not None and err != "": + return TextObservation(text=err) + + return None + + +class EditCodeStep(Step): + # Might make an even more specific atomic step, which is "apply file edit" + range_in_files: List[RangeInFile] + prompt: str # String with {code} somewhere + name: str = "Edit code" + + _edit_diffs: Union[List[EditDiff], None] = None + _prompt: Union[str, None] = None + _completion: Union[str, None] = None + + async def describe(self, llm: LLM) -> Coroutine[str, None, None]: + if self._edit_diffs is None: + return "Editing files: " + ", ".join(map(lambda rif: rif.filepath, self.range_in_files)) + elif len(self._edit_diffs) == 0: + return "No edits made" + else: + return llm.complete(dedent(f"""{self._prompt}{self._completion} + + Maximally concise summary of changes in bullet points (can use markdown): + """)) + + async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: + rif_with_contents = [] + for range_in_file in self.range_in_files: + file_contents = await sdk.ide.readRangeInFile(range_in_file) + rif_with_contents.append( + RangeInFileWithContents.from_range_in_file(range_in_file, file_contents)) + enc_dec = MarkdownStyleEncoderDecoder(rif_with_contents) + code_string = enc_dec.encode() + prompt = self.prompt.format(code=code_string) + + completion = sdk.llm.complete(prompt) + + # Temporarily doing this to generate description. + self._prompt = prompt + self._completion = completion + + file_edits = enc_dec.decode(completion) + + self._edit_diffs = [] + for file_edit in file_edits: + diff = await sdk.apply_filesystem_edit(file_edit) + self._edit_diffs.append(diff) + + for filepath in set([file_edit.filepath for file_edit in file_edits]): + await sdk.ide.saveFile(filepath) + await sdk.ide.setFileOpen(filepath) + + return None + + +class EditFileStep(Step): + filepath: str + prompt: str + hide: bool = True + + async def describe(self, llm: LLM) -> Coroutine[str, None, None]: + return "Editing file: " + self.filepath + + async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: + file_contents = await sdk.ide.readFile(self.filepath) + await sdk.run_step(EditCodeStep( + range_in_files=[RangeInFile.from_entire_file( + self.filepath, file_contents)], + prompt=self.prompt + )) + + class ManualEditStep(ReversibleStep): edit_diff: EditDiff hide: bool = True @@ -89,3 +186,31 @@ class UserInputStep(Step): async def run(self, sdk: ContinueSDK) -> Coroutine[UserInputObservation, None, None]: return UserInputObservation(user_input=self.user_input) + + +class WaitForUserInputStep(Step): + prompt: str + name: str = "Waiting for user input" + + _description: Union[str, None] = None + + async def describe(self, llm: LLM) -> Coroutine[str, None, None]: + return self.prompt + + async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: + self._description = self.prompt + resp = await sdk.wait_for_user_input() + return TextObservation(text=resp) + + +class WaitForUserConfirmationStep(Step): + prompt: str + name: str = "Waiting for user confirmation" + + async def describe(self, llm: LLM) -> Coroutine[str, None, None]: + return self.prompt + + async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: + self._description = self.prompt + resp = await sdk.wait_for_user_input() + return TextObservation(text=resp) diff --git a/continuedev/src/continuedev/libs/steps/draft/abstract_method.py b/continuedev/src/continuedev/libs/steps/draft/abstract_method.py index 927d93fd..f3131c4b 100644 --- a/continuedev/src/continuedev/libs/steps/draft/abstract_method.py +++ b/continuedev/src/continuedev/libs/steps/draft/abstract_method.py @@ -1,4 +1,5 @@ -from ...core import ContinueSDK, Step +from ....core.sdk import ContinueSDK +from ....core.main import Step class ImplementAbstractMethodStep(Step): diff --git a/continuedev/src/continuedev/libs/steps/draft/dlt.py b/continuedev/src/continuedev/libs/steps/draft/dlt.py index 608f089a..5ba5692a 100644 --- a/continuedev/src/continuedev/libs/steps/draft/dlt.py +++ b/continuedev/src/continuedev/libs/steps/draft/dlt.py @@ -1,6 +1,7 @@ from textwrap import dedent from ....models.filesystem_edit import AddFile -from ...core import Step, ContinueSDK +from ....core.main import Step +from ....core.sdk import ContinueSDK from ..main import WaitForUserInputStep diff --git a/continuedev/src/continuedev/libs/steps/draft/redux.py b/continuedev/src/continuedev/libs/steps/draft/redux.py index 52a8fbd8..efaa9ba4 100644 --- a/continuedev/src/continuedev/libs/steps/draft/redux.py +++ b/continuedev/src/continuedev/libs/steps/draft/redux.py @@ -1,7 +1,6 @@ -from textwrap import dedent -from ....models.filesystem_edit import AddFile -from ...core import Step, ContinueSDK -from ..main import WaitForUserInputStep, EditFileStep +from ....core.main import Step +from ....core.sdk import ContinueSDK +from ..core.core import EditFileStep class EditReduxStateStep(Step): diff --git a/continuedev/src/continuedev/libs/steps/draft/typeorm.py b/continuedev/src/continuedev/libs/steps/draft/typeorm.py index 9d058f1e..d06a6fb4 100644 --- a/continuedev/src/continuedev/libs/steps/draft/typeorm.py +++ b/continuedev/src/continuedev/libs/steps/draft/typeorm.py @@ -1,5 +1,6 @@ from textwrap import dedent -from ...core import Step, ContinueSDK +from ....core.main import Step +from ....core.sdk import ContinueSDK class CreateTableStep(Step): diff --git a/continuedev/src/continuedev/libs/steps/main.py b/continuedev/src/continuedev/libs/steps/main.py index 555c1180..f28cb23f 100644 --- a/continuedev/src/continuedev/libs/steps/main.py +++ b/continuedev/src/continuedev/libs/steps/main.py @@ -1,18 +1,39 @@ -import time from typing import Callable, Coroutine, List, Union +from ..util.traceback_parsers import parse_python_traceback from ..llm import LLM from ...models.main import Traceback, Range from ...models.filesystem_edit import EditDiff, FileEdit from ...models.filesystem import RangeInFile, RangeInFileWithContents -from ..observation import Observation, TextObservation +from ...core.observation import Observation, TextObservation, TracebackObservation from ..llm.prompt_utils import MarkdownStyleEncoderDecoder from textwrap import dedent -from ..core import History, Policy, Step, ContinueSDK, Observation +from ...core.main import History, Policy, Step, ContinueSDK, Observation import subprocess -from ..util.traceback_parsers import parse_python_traceback -from ..observation import TracebackObservation import json +from .core.core import EditCodeStep + + +class RunCodeStep(Step): + cmd: str + + async def describe(self, llm: LLM) -> Coroutine[str, None, None]: + return f"Ran command: `{self.cmd}`" + + async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: + result = subprocess.run( + self.cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout = result.stdout.decode("utf-8") + stderr = result.stderr.decode("utf-8") + print(stdout, stderr) + + # If it fails, return the error + tb = parse_python_traceback(stdout) or parse_python_traceback(stderr) + if tb: + return TracebackObservation(traceback=tb) + else: + self.hide = True + return None class RunPolicyUntilDoneStep(Step): @@ -51,149 +72,6 @@ class RunCommandStep(Step): return TextObservation(text=stdout) -def ShellCommandsStep(Step): - cmds: List[str] - name: str = "Run Shell Commands" - - async def describe(self, llm: LLM) -> Coroutine[str, None, None]: - return "\n".join(self.cmds) - - async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - cwd = await sdk.ide.getWorkspaceDirectory() - - process = subprocess.Popen( - '/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=cwd) - - stdin_input = "\n".join(self.cmds) - out, err = process.communicate(stdin_input.encode()) - - # TODO: How to await?? - - # If it fails, return the error - if err is not None and err != "": - return TextObservation(text=err) - - return None - - -class WaitForUserInputStep(Step): - prompt: str - name: str = "Waiting for user input" - - _description: Union[str, None] = None - - async def describe(self, llm: LLM) -> Coroutine[str, None, None]: - return self.prompt - - async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - self._description = self.prompt - resp = await sdk.wait_for_user_input() - return TextObservation(text=resp) - - -class WaitForUserConfirmationStep(Step): - prompt: str - name: str = "Waiting for user confirmation" - - async def describe(self, llm: LLM) -> Coroutine[str, None, None]: - return self.prompt - - async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - self._description = self.prompt - resp = await sdk.wait_for_user_input() - return TextObservation(text=resp) - - -class RunCodeStep(Step): - cmd: str - - async def describe(self, llm: LLM) -> Coroutine[str, None, None]: - return f"Ran command: `{self.cmd}`" - - async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - result = subprocess.run( - self.cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout = result.stdout.decode("utf-8") - stderr = result.stderr.decode("utf-8") - print(stdout, stderr) - - # If it fails, return the error - tb = parse_python_traceback(stdout) or parse_python_traceback(stderr) - if tb: - return TracebackObservation(traceback=tb) - else: - self.hide = True - return None - - -class EditCodeStep(Step): - # Might make an even more specific atomic step, which is "apply file edit" - range_in_files: List[RangeInFile] - prompt: str # String with {code} somewhere - name: str = "Edit code" - - _edit_diffs: Union[List[EditDiff], None] = None - _prompt: Union[str, None] = None - _completion: Union[str, None] = None - - async def describe(self, llm: LLM) -> Coroutine[str, None, None]: - if self._edit_diffs is None: - return "Editing files: " + ", ".join(map(lambda rif: rif.filepath, self.range_in_files)) - elif len(self._edit_diffs) == 0: - return "No edits made" - else: - return llm.complete(dedent(f"""{self._prompt}{self._completion} - - Maximally concise summary of changes in bullet points (can use markdown): - """)) - - async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - rif_with_contents = [] - for range_in_file in self.range_in_files: - file_contents = await sdk.ide.readRangeInFile(range_in_file) - rif_with_contents.append( - RangeInFileWithContents.from_range_in_file(range_in_file, file_contents)) - enc_dec = MarkdownStyleEncoderDecoder(rif_with_contents) - code_string = enc_dec.encode() - prompt = self.prompt.format(code=code_string) - - completion = sdk.llm.complete(prompt) - - # Temporarily doing this to generate description. - self._prompt = prompt - self._completion = completion - - file_edits = enc_dec.decode(completion) - - self._edit_diffs = [] - for file_edit in file_edits: - diff = await sdk.apply_filesystem_edit(file_edit) - self._edit_diffs.append(diff) - - for filepath in set([file_edit.filepath for file_edit in file_edits]): - await sdk.ide.saveFile(filepath) - await sdk.ide.setFileOpen(filepath) - - return None - - -class EditFileStep(Step): - filepath: str - prompt: str - hide: bool = True - - async def describe(self, llm: LLM) -> Coroutine[str, None, None]: - return "Editing file: " + self.filepath - - async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - file_contents = await sdk.ide.readFile(self.filepath) - await sdk.run_step(EditCodeStep( - range_in_files=[RangeInFile.from_entire_file( - self.filepath, file_contents)], - prompt=self.prompt - )) - - class FasterEditHighlightedCodeStep(Step): user_input: str hide = True diff --git a/continuedev/src/continuedev/libs/steps/migration.py b/continuedev/src/continuedev/libs/steps/migration.py index 04296836..f044a60f 100644 --- a/continuedev/src/continuedev/libs/steps/migration.py +++ b/continuedev/src/continuedev/libs/steps/migration.py @@ -3,7 +3,7 @@ from ...models.filesystem import RangeInFile from .main import EditCodeStep, RunCommandStep -from ..core import Step +from ...core.main import Step class MigrationStep(Step): diff --git a/continuedev/src/continuedev/libs/steps/nate.py b/continuedev/src/continuedev/libs/steps/nate.py index 80436fa4..a0e728e5 100644 --- a/continuedev/src/continuedev/libs/steps/nate.py +++ b/continuedev/src/continuedev/libs/steps/nate.py @@ -1,14 +1,13 @@ -import asyncio from textwrap import dedent import time from typing import Coroutine, Union -from ...models.main import Range from ...models.filesystem import RangeInFile from ...models.filesystem_edit import AddDirectory, AddFile -from ..observation import Observation, TextObservation -from ..core import Step, ContinueSDK -from .main import EditCodeStep, EditFileStep, RunCommandStep, WaitForUserConfirmationStep +from ...core.observation import Observation, TextObservation +from ...core.main import Step, ContinueSDK +from .main import RunCommandStep +from .core.core import WaitForUserConfirmationStep, EditCodeStep, EditFileStep import os diff --git a/continuedev/src/continuedev/libs/steps/pytest.py b/continuedev/src/continuedev/libs/steps/pytest.py index e53eb465..b4e6dfd2 100644 --- a/continuedev/src/continuedev/libs/steps/pytest.py +++ b/continuedev/src/continuedev/libs/steps/pytest.py @@ -1,6 +1,6 @@ from textwrap import dedent from ...models.filesystem_edit import AddDirectory, AddFile -from ..core import Step, ContinueSDK +from ...core.main import Step, ContinueSDK import os diff --git a/continuedev/src/continuedev/libs/steps/ty.py b/continuedev/src/continuedev/libs/steps/ty.py index 1eb6271d..5ff03f04 100644 --- a/continuedev/src/continuedev/libs/steps/ty.py +++ b/continuedev/src/continuedev/libs/steps/ty.py @@ -2,9 +2,11 @@ import subprocess from ...models.main import Position, Range from ...models.filesystem import RangeInFile from ...models.filesystem_edit import AddDirectory, AddFile, FileEdit -from ..observation import DictObservation -from ..core import History, Step, ContinueSDK, Policy -from .main import EditCodeStep, RunCommandStep, WaitForUserInputStep, WaitForUserConfirmationStep +from ...core.observation import DictObservation +from ...core.main import History, Step, Policy +from ...core.sdk import ContinueSDK +from .main import RunCommandStep +from ..steps.core.core import EditCodeStep, WaitForUserConfirmationStep, WaitForUserInputStep source_name = "weather_api" diff --git a/continuedev/src/continuedev/plugins/policy/libs/alternate.py b/continuedev/src/continuedev/plugins/policy/libs/alternate.py index 5bfbb821..3087c059 100644 --- a/continuedev/src/continuedev/plugins/policy/libs/alternate.py +++ b/continuedev/src/continuedev/plugins/policy/libs/alternate.py @@ -1,7 +1,5 @@ from plugins import policy -from ....libs.observation import Observation -from ....libs.steps import Step -from ....libs.core import History +from ....core.main import History, Step class AlternatingPolicy: diff --git a/continuedev/src/continuedev/plugins/step/hookspecs.py b/continuedev/src/continuedev/plugins/step/hookspecs.py index 4309bad3..a5714fc5 100644 --- a/continuedev/src/continuedev/plugins/step/hookspecs.py +++ b/continuedev/src/continuedev/plugins/step/hookspecs.py @@ -1,6 +1,8 @@ from typing import Coroutine import pluggy -from ...libs.core import ContinueSDK, Step, Observation +from ...core.main import Step +from ...core.observation import Observation +from ...core.sdk import ContinueSDK hookspec = pluggy.HookspecMarker("continue.step") diff --git a/continuedev/src/continuedev/server/notebook.py b/continuedev/src/continuedev/server/notebook.py index 5eb151d7..bfd7a09c 100644 --- a/continuedev/src/continuedev/server/notebook.py +++ b/continuedev/src/continuedev/server/notebook.py @@ -5,14 +5,14 @@ from pydantic import BaseModel from uvicorn.main import Server from ..models.filesystem_edit import FileEditWithFullContents -from ..libs.policy import DemoPolicy -from ..libs.core import FullState, History, Step -from ..libs.agent import Agent +from ..core.policy import DemoPolicy +from ..core.main import FullState, History, Step +from ..core.agent import Agent from ..libs.steps.nate import ImplementAbstractMethodStep -from ..libs.observation import Observation +from ..core.observation import Observation from ..libs.llm.openai import OpenAI from .ide_protocol import AbstractIdeProtocolServer -from ..libs.env import openai_api_key +from ..core.env import openai_api_key import asyncio import nest_asyncio nest_asyncio.apply() -- cgit v1.2.3-70-g09d2