From 4c9ed33c14df9e37d7d11faafb4182a3534141ca Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Mon, 5 Jun 2023 12:09:13 -0400 Subject: Enter button on user input --- continuedev/src/continuedev/core/policy.py | 5 ++++- continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py | 9 ++++++--- continuedev/src/continuedev/steps/core/core.py | 7 ++++++- 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'continuedev/src') diff --git a/continuedev/src/continuedev/core/policy.py b/continuedev/src/continuedev/core/policy.py index 4287bb6e..e65b6c9d 100644 --- a/continuedev/src/continuedev/core/policy.py +++ b/continuedev/src/continuedev/core/policy.py @@ -17,7 +17,10 @@ class DemoPolicy(Policy): def next(self, history: History) -> Step: # At the very start, run initial Steps spcecified in the config if history.get_current() is None: - return MessageStep(message="Welcome to Continue!") >> SetupContinueWorkspaceStep() >> CreateCodebaseIndexChroma() >> StepsOnStartupStep() + return (MessageStep(message="Welcome to Continue!") >> + SetupContinueWorkspaceStep() >> + CreateCodebaseIndexChroma() >> + StepsOnStartupStep()) observation = history.get_current().observation if observation is not None and isinstance(observation, UserInputObservation): diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py index 4a4604d6..55c25da4 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py @@ -11,7 +11,7 @@ class CreatePipelineRecipe(Step): hide: bool = True async def run(self, sdk: ContinueSDK): - await sdk.run_step( + text_observation = await sdk.run_step( MessageStep(message=dedent("""\ This recipe will walk you through the process of creating a dlt pipeline for your chosen data source. With the help of Continue, you will: - Create a Python virtual environment with dlt installed @@ -21,7 +21,10 @@ class CreatePipelineRecipe(Step): - Test that the API call works - Load the data into a local DuckDB instance - Write a query to view the data""")) >> - WaitForUserInputStep(prompt="What API do you want to load data from?") >> - SetupPipelineStep(api_description="WeatherAPI.com API") >> + WaitForUserInputStep( + prompt="What API do you want to load data from?") + ) + await sdk.run_step( + SetupPipelineStep(api_description=text_observation.text) >> ValidatePipelineStep() ) diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index d7f7a307..04446787 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -191,13 +191,18 @@ class WaitForUserInputStep(Step): name: str = "Waiting for user input" _description: Union[str, None] = None + _response: Union[str, None] = None async def describe(self, models: Models) -> Coroutine[str, None, None]: - return self.prompt + if self._response is None: + return self.prompt + else: + return self.prompt + "\n\n" + self._response async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: self._description = self.prompt resp = await sdk.wait_for_user_input() + self._response = resp return TextObservation(text=resp) -- cgit v1.2.3-70-g09d2 From 04aa13340b7a621a9ff678a3c0cfc1d9aa9fb646 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 6 Jun 2023 00:21:15 -0400 Subject: many design improvements --- continuedev/src/continuedev/core/autopilot.py | 34 +++++++--- continuedev/src/continuedev/core/main.py | 30 ++++++--- continuedev/src/continuedev/core/policy.py | 7 +- continuedev/src/continuedev/core/sdk.py | 21 ++++-- .../recipes/CreatePipelineRecipe/main.py | 2 +- .../recipes/CreatePipelineRecipe/steps.py | 62 +++++++++++++----- continuedev/src/continuedev/server/ide.py | 11 ++++ continuedev/src/continuedev/server/ide_protocol.py | 8 +++ continuedev/src/continuedev/steps/core/core.py | 27 ++++---- extension/package.json | 4 +- extension/react-app/src/components/DebugPanel.tsx | 15 ++--- .../react-app/src/components/StepContainer.tsx | 52 ++++++++------- extension/react-app/src/components/index.ts | 11 +++- extension/react-app/src/tabs/chat/MessageDiv.tsx | 1 - extension/react-app/src/tabs/gui.tsx | 74 +++++++++++++++++----- extension/src/continueIdeClient.ts | 39 +++++++++++- 16 files changed, 286 insertions(+), 112 deletions(-) (limited to 'continuedev/src') diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index db06c975..d55e521b 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -1,13 +1,13 @@ import traceback import time -from typing import Callable, Coroutine, List +from typing import Any, Callable, Coroutine, Dict, List from ..models.filesystem_edit import FileEditWithFullContents from ..libs.llm import LLM from .observation import Observation, InternalErrorObservation 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 .main import Context, ContinueCustomException, Policy, History, FullState, Step, HistoryNode from ..steps.core.core import ReversibleStep, ManualEditStep, UserInputStep from ..libs.util.telemetry import capture_event from .sdk import ContinueSDK @@ -18,6 +18,7 @@ class Autopilot(ContinueBaseModel): policy: Policy ide: AbstractIdeProtocolServer history: History = History.from_empty() + context: Context = Context() _on_update_callbacks: List[Callable[[FullState], None]] = [] _active: bool = False @@ -26,6 +27,10 @@ class Autopilot(ContinueBaseModel): _user_input_queue = AsyncSubscriptionQueue() + @property + def continue_sdk(self) -> ContinueSDK: + return ContinueSDK(self) + class Config: arbitrary_types_allowed = True @@ -60,7 +65,7 @@ class Autopilot(ContinueBaseModel): current_step = self.history.get_current().step self.history.step_back() if issubclass(current_step.__class__, ReversibleStep): - await current_step.reverse(ContinueSDK(self)) + await current_step.reverse(self.continue_sdk) await self.update_subscribers() except Exception as e: @@ -105,7 +110,16 @@ class Autopilot(ContinueBaseModel): self._step_depth += 1 try: - observation = await step(ContinueSDK(self)) + observation = await step(self.continue_sdk) + except ContinueCustomException as e: + # Attach an InternalErrorObservation to the step and unhide it. + error_string = e.message + print( + f"\n{error_string}\n{e}") + + observation = InternalErrorObservation( + error=error_string) + step.hide = False except Exception as e: # Attach an InternalErrorObservation to the step and unhide it. error_string = '\n\n'.join( @@ -125,11 +139,13 @@ class Autopilot(ContinueBaseModel): await self.update_subscribers() # Update its description - async def update_description(): - step._set_description(await step.describe(ContinueSDK(self).models)) - # Update subscribers with new description - await self.update_subscribers() - asyncio.create_task(update_description()) + if step.description is None: + async def update_description(): + step.description = await step.describe(self.continue_sdk.models) + # Update subscribers with new description + await self.update_subscribers() + + asyncio.create_task(update_description()) return observation diff --git a/continuedev/src/continuedev/core/main.py b/continuedev/src/continuedev/core/main.py index b2b97bae..17b30e96 100644 --- a/continuedev/src/continuedev/core/main.py +++ b/continuedev/src/continuedev/core/main.py @@ -105,7 +105,7 @@ class Policy(ContinueBaseModel): class Step(ContinueBaseModel): name: str = None hide: bool = False - _description: Union[str, None] = None + description: Union[str, None] = None system_message: Union[str, None] = None @@ -113,17 +113,14 @@ class Step(ContinueBaseModel): copy_on_model_validation = False async def describe(self, models: Models) -> Coroutine[str, None, None]: - if self._description is not None: - return self._description + 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 + if self.description is not None: + d["description"] = self.description else: d["description"] = "`Description loading...`" return d @@ -173,4 +170,21 @@ class Validator(Step): raise NotImplementedError +class Context: + key_value: Dict[str, str] = {} + + def set(self, key: str, value: str): + self.key_value[key] = value + + def get(self, key: str) -> str: + return self.key_value[key] + + +class ContinueCustomException(Exception): + message: str + + def __init__(self, message: str): + self.message = message + + HistoryNode.update_forward_refs() diff --git a/continuedev/src/continuedev/core/policy.py b/continuedev/src/continuedev/core/policy.py index e65b6c9d..4934497d 100644 --- a/continuedev/src/continuedev/core/policy.py +++ b/continuedev/src/continuedev/core/policy.py @@ -17,9 +17,10 @@ class DemoPolicy(Policy): def next(self, history: History) -> Step: # At the very start, run initial Steps spcecified in the config if history.get_current() is None: - return (MessageStep(message="Welcome to Continue!") >> - SetupContinueWorkspaceStep() >> - CreateCodebaseIndexChroma() >> + return ( + MessageStep(name="Welcome to Continue!", message="") >> + # SetupContinueWorkspaceStep() >> + # CreateCodebaseIndexChroma() >> StepsOnStartupStep()) observation = history.get_current().observation diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py index 8317a3d1..690949f1 100644 --- a/continuedev/src/continuedev/core/sdk.py +++ b/continuedev/src/continuedev/core/sdk.py @@ -11,7 +11,7 @@ from ..libs.llm.hf_inference_api import HuggingFaceInferenceAPI from ..libs.llm.openai import OpenAI from .observation import Observation from ..server.ide_protocol import AbstractIdeProtocolServer -from .main import History, Step +from .main import Context, ContinueCustomException, History, Step from ..steps.core.core import * @@ -44,6 +44,7 @@ class ContinueSDK(AbstractContinueSDK): ide: AbstractIdeProtocolServer steps: ContinueSDKSteps models: Models + context: Context __autopilot: Autopilot def __init__(self, autopilot: Autopilot): @@ -51,6 +52,7 @@ class ContinueSDK(AbstractContinueSDK): self.__autopilot = autopilot self.steps = ContinueSDKSteps(self) self.models = Models(self) + self.context = autopilot.context @property def history(self) -> History: @@ -64,8 +66,8 @@ class ContinueSDK(AbstractContinueSDK): async def run_step(self, step: Step) -> Coroutine[Observation, None, None]: return await self.__autopilot._run_singular_step(step) - async def apply_filesystem_edit(self, edit: FileSystemEdit): - return await self.run_step(FileSystemEditStep(edit=edit)) + async def apply_filesystem_edit(self, edit: FileSystemEdit, name: str = None, description: str = None): + return await self.run_step(FileSystemEditStep(edit=edit, description=description, **({'name': name} if name else {}))) async def wait_for_user_input(self) -> str: return await self.__autopilot.wait_for_user_input() @@ -73,18 +75,20 @@ class ContinueSDK(AbstractContinueSDK): async def wait_for_user_confirmation(self, prompt: str): return await self.run_step(WaitForUserConfirmationStep(prompt=prompt)) - async def run(self, commands: Union[List[str], str], cwd: str = None): + async def run(self, commands: Union[List[str], str], cwd: str = None, name: str = None, description: str = None): commands = commands if isinstance(commands, List) else [commands] - return await self.run_step(ShellCommandsStep(cmds=commands, cwd=cwd)) + return await self.run_step(ShellCommandsStep(cmds=commands, cwd=cwd, description=description, **({'name': name} if name else {}))) - async def edit_file(self, filename: str, prompt: str): + async def edit_file(self, filename: str, prompt: str, name: str = None, description: str = None): filepath = await self._ensure_absolute_path(filename) await self.ide.setFileOpen(filepath) contents = await self.ide.readFile(filepath) await self.run_step(EditCodeStep( range_in_files=[RangeInFile.from_entire_file(filepath, 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' + 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', + description=description, + **({'name': name} if name else {}) )) async def append_to_file(self, filename: str, content: str): @@ -126,3 +130,6 @@ class ContinueSDK(AbstractContinueSDK): def set_loading_message(self, message: str): # self.__autopilot.set_loading_message(message) raise NotImplementedError() + + def raise_exception(self, message: str): + raise ContinueCustomException(message) diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py index 55c25da4..1206db0e 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py @@ -12,7 +12,7 @@ class CreatePipelineRecipe(Step): async def run(self, sdk: ContinueSDK): text_observation = await sdk.run_step( - MessageStep(message=dedent("""\ + MessageStep(name="Building your first dlt pipeline", message=dedent("""\ This recipe will walk you through the process of creating a dlt pipeline for your chosen data source. With the help of Continue, you will: - Create a Python virtual environment with dlt installed - Run `dlt init` to generate a pipeline template diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py index ef5e3b43..3c8277c0 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py @@ -1,8 +1,12 @@ +import os +import subprocess from textwrap import dedent +from ...models.main import Range +from ...models.filesystem import RangeInFile from ...steps.main import MessageStep from ...core.sdk import Models -from ...core.observation import DictObservation +from ...core.observation import DictObservation, InternalErrorObservation from ...models.filesystem_edit import AddFile from ...core.main import Step from ...core.sdk import ContinueSDK @@ -33,45 +37,69 @@ class SetupPipelineStep(Step): f'dlt init {source_name} duckdb', 'Y', 'pip install -r requirements.txt' - ]) - + ], description=dedent(f"""\ + Running the following commands: + - `python3 -m venv env`: Create a Python virtual environment + - `source env/bin/activate`: Activate the virtual environment + - `pip install dlt`: Install dlt + - `dlt init {source_name} duckdb`: Create a new dlt pipeline called {source_name} that loads data into a local DuckDB instance + - `pip install -r requirements.txt`: Install the Python dependencies for the pipeline""")) + + await sdk.wait_for_user_confirmation("Wait for the commands to finish running, then press `Continue`") # editing the resource function to call the requested API + await sdk.ide.highlightCode(RangeInFile(filepath=os.path.join(await sdk.ide.getWorkspaceDirectory(), filename), range=Range.from_shorthand(15, 0, 30, 0)), "#00ff0022") + await sdk.edit_file( filename=filename, - prompt=f'Edit the resource function to call the API described by this: {self.api_description}' + prompt=f'Edit the resource function to call the API described by this: {self.api_description}', + name="Edit the resource function to call the API" ) # wait for user to put API key in secrets.toml await sdk.ide.setFileOpen(await sdk.ide.getWorkspaceDirectory() + "/.dlt/secrets.toml") await sdk.wait_for_user_confirmation("If this service requires an API key, please add it to the `secrets.toml` file and then press `Continue`") - return DictObservation(values={"source_name": source_name}) + + sdk.context.set("source_name", source_name) class ValidatePipelineStep(Step): hide: bool = True async def run(self, sdk: ContinueSDK): - source_name = sdk.history.last_observation().values["source_name"] + workspace_dir = await sdk.ide.getWorkspaceDirectory() + source_name = sdk.context.get("source_name") filename = f'{source_name}.py' - await sdk.run_step(MessageStep(message=dedent("""\ - This step will validate that your dlt pipeline is working as expected: - - Test that the API call works - - Load the data into a local DuckDB instance - - Write a query to view the data - """))) + # await sdk.run_step(MessageStep(name="Validate the pipeline", message=dedent("""\ + # Next, we will validate that your dlt pipeline is working as expected: + # - Test that the API call works + # - Load the data into a local DuckDB instance + # - Write a query to view the data + # """))) # test that the API call works - await sdk.run(f'python3 {filename}') + + p = subprocess.run( + ['python3', f'{filename}'], capture_output=True, text=True, cwd=workspace_dir) + err = p.stderr + + # If it fails, return the error + if err is not None and err != "": + sdk.raise_exception( + f"Error while running pipeline. Fix the resource function in {filename} and rerun this step: \n\n" + err) + + await sdk.run(f'python3 {filename}', name="Test the pipeline", description=f"Running python3 {filename} to test loading data from the API") # remove exit() from the main main function await sdk.edit_file( filename=filename, - prompt='Remove exit() from the main function' + prompt='Remove exit() from the main function', + name="Remove early exit() from main function", + description="Remove the `exit()` call from the main function in the pipeline file so that the data is loaded into DuckDB" ) # load the data into the DuckDB instance - await sdk.run(f'python3 {filename}') + await sdk.run(f'python3 {filename}', name="Load data into DuckDB", description=f"Running python3 {filename} to load data into DuckDB") table_name = f"{source_name}.{source_name}_resource" tables_query_code = dedent(f'''\ @@ -89,5 +117,5 @@ class ValidatePipelineStep(Step): ''') query_filename = (await sdk.ide.getWorkspaceDirectory()) + "/query.py" - await sdk.apply_filesystem_edit(AddFile(filepath=query_filename, content=tables_query_code)) - await sdk.run('env/bin/python3 query.py') + await sdk.apply_filesystem_edit(AddFile(filepath=query_filename, content=tables_query_code), name="Add query.py file", description="Adding a file called `query.py` to the workspace that will run a test query on the DuckDB instance") + await sdk.run('env/bin/python3 query.py', name="Run test query", description="Running `env/bin/python3 query.py` to test that the data was loaded into DuckDB as expected") diff --git a/continuedev/src/continuedev/server/ide.py b/continuedev/src/continuedev/server/ide.py index eec5b607..073e1dba 100644 --- a/continuedev/src/continuedev/server/ide.py +++ b/continuedev/src/continuedev/server/ide.py @@ -133,6 +133,17 @@ class IdeProtocolServer(AbstractIdeProtocolServer): "sessionId": session_id }) + async def highlightCode(self, range_in_file: RangeInFile, color: str): + await self._send_json("highlightCode", { + "rangeInFile": range_in_file.dict(), + "color": color + }) + + async def runCommand(self, command: str): + await self._send_json("runCommand", { + "command": command + }) + async def showSuggestionsAndWait(self, suggestions: List[FileEdit]) -> bool: ids = [str(uuid.uuid4()) for _ in suggestions] for i in range(len(suggestions)): diff --git a/continuedev/src/continuedev/server/ide_protocol.py b/continuedev/src/continuedev/server/ide_protocol.py index 8f155415..f42de68f 100644 --- a/continuedev/src/continuedev/server/ide_protocol.py +++ b/continuedev/src/continuedev/server/ide_protocol.py @@ -82,3 +82,11 @@ class AbstractIdeProtocolServer(ABC): @abstractmethod async def getUserSecret(self, key: str): """Get a user secret""" + + @abstractmethod + async def highlightCode(self, range_in_file: RangeInFile, color: str): + """Highlight code""" + + @abstractmethod + async def runCommand(self, command: str): + """Run a command""" diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index ad468595..99786b00 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -55,18 +55,21 @@ class ShellCommandsStep(Step): 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) + for cmd in self.cmds: + await sdk.ide.runCommand(cmd) - stdin_input = "\n".join(self.cmds) - out, err = process.communicate(stdin_input.encode()) + # process = subprocess.Popen( + # '/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=cwd) - # If it fails, return the error - if err is not None and err != "": - self._err_text = err - return TextObservation(text=err) + # stdin_input = "\n".join(self.cmds) + # out, err = process.communicate(stdin_input.encode()) - return None + # # If it fails, return the error + # if err is not None and err != "": + # self._err_text = err + # return TextObservation(text=err) + + # return None class EditCodeStep(Step): @@ -197,10 +200,10 @@ class WaitForUserInputStep(Step): if self._response is None: return self.prompt else: - return self.prompt + "\n\n" + self._response + return f"{self.prompt}\n\n`{self._response}`" async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - self._description = self.prompt + self.description = self.prompt resp = await sdk.wait_for_user_input() self._response = resp return TextObservation(text=resp) @@ -214,7 +217,7 @@ class WaitForUserConfirmationStep(Step): return self.prompt async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - self._description = self.prompt + self.description = self.prompt resp = await sdk.wait_for_user_input() self.hide = True return TextObservation(text=resp) diff --git a/extension/package.json b/extension/package.json index 7bd48f98..c834f402 100644 --- a/extension/package.json +++ b/extension/package.json @@ -42,12 +42,12 @@ "description": "The URL of the Continue server to use." }, "continue.OPENAI_API_KEY": { - "type": "string", + "type": "password", "default": "", "description": "The OpenAI API key to use for code generation." }, "continue.HUGGING_FACE_TOKEN": { - "type": "string", + "type": "password", "default": "", "description": "The Hugging Face API token to use for code generation." } diff --git a/extension/react-app/src/components/DebugPanel.tsx b/extension/react-app/src/components/DebugPanel.tsx index 9dacc624..11ec2fe2 100644 --- a/extension/react-app/src/components/DebugPanel.tsx +++ b/extension/react-app/src/components/DebugPanel.tsx @@ -9,7 +9,7 @@ import { } from "../redux/slices/configSlice"; import { setHighlightedCode } from "../redux/slices/miscSlice"; import { updateFileSystem } from "../redux/slices/debugContexSlice"; -import { buttonColor, defaultBorderRadius, vscBackground } from "."; +import { defaultBorderRadius, secondaryDark, vscBackground } from "."; interface DebugPanelProps { tabs: { element: React.ReactElement; @@ -19,14 +19,15 @@ interface DebugPanelProps { const GradientContainer = styled.div` // Uncomment to get gradient border - background: linear-gradient( + /* background: linear-gradient( 101.79deg, #12887a 0%, #87245c 37.64%, #e12637 65.98%, #ffb215 110.45% - ); + ); */ /* padding: 10px; */ + background-color: ${secondaryDark}; margin: 0; height: 100%; /* border: 1px solid white; */ @@ -36,11 +37,8 @@ const GradientContainer = styled.div` const MainDiv = styled.div` height: 100%; border-radius: ${defaultBorderRadius}; - overflow-y: scroll; - scrollbar-gutter: stable both-edges; scrollbar-base-color: transparent; - /* background: ${vscBackground}; */ - background-color: #1e1e1ede; + background-color: ${vscBackground}; `; const TabBar = styled.div<{ numTabs: number }>` @@ -105,9 +103,6 @@ function DebugPanel(props: DebugPanelProps) { { if (e.key === "Enter") { diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index a5a1c5dc..25287d32 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -96,6 +96,12 @@ class IdeProtocolClient { fileEdit, }); break; + case "highlightCode": + this.highlightCode(data.rangeInFile, data.color); + break; + case "runCommand": + this.runCommand(data.command); + break; case "saveFile": this.saveFile(data.filepath); break; @@ -117,6 +123,28 @@ class IdeProtocolClient { // ------------------------------------ // // On message handlers + async highlightCode(rangeInFile: RangeInFile, color: string) { + const range = new vscode.Range( + rangeInFile.range.start.line, + rangeInFile.range.start.character, + rangeInFile.range.end.line, + rangeInFile.range.end.character + ); + const editor = await openEditorAndRevealRange( + rangeInFile.filepath, + range, + vscode.ViewColumn.One + ); + if (editor) { + editor.setDecorations( + vscode.window.createTextEditorDecorationType({ + backgroundColor: color, + }), + [range] + ); + } + } + showSuggestion(edit: FileEdit) { // showSuggestion already exists showSuggestion( @@ -289,7 +317,16 @@ class IdeProtocolClient { } runCommand(command: string) { - vscode.window.terminals[0].sendText(command, true); + if (vscode.window.terminals.length === 0) { + const terminal = vscode.window.createTerminal(); + terminal.show(); + terminal.sendText("bash", true); + terminal.sendText(command, true); + return; + } + const terminal = vscode.window.terminals[0]; + terminal.show(); + terminal.sendText(command, true); // But need to know when it's done executing... } } -- cgit v1.2.3-70-g09d2 From 7af8208d0adb9586e60bd67fd6f4f321a35262d8 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 6 Jun 2023 17:50:50 -0400 Subject: trying to reliably capture terminal output in vsc --- continuedev/src/continuedev/core/autopilot.py | 4 +- continuedev/src/continuedev/core/main.py | 4 +- continuedev/src/continuedev/core/observation.py | 1 + continuedev/src/continuedev/core/sdk.py | 8 +- .../recipes/CreatePipelineRecipe/main.py | 2 +- .../recipes/CreatePipelineRecipe/steps.py | 17 +- continuedev/src/continuedev/server/ide.py | 12 +- continuedev/src/continuedev/server/ide_protocol.py | 2 +- continuedev/src/continuedev/steps/core/core.py | 6 +- extension/esbuild.mjs | 14 + extension/package-lock.json | 1132 +------------------- extension/package.json | 5 +- .../react-app/src/components/StepContainer.tsx | 12 +- .../react-app/src/components/ToggleErrorDiv.tsx | 41 + extension/react-app/src/tabs/gui.tsx | 4 + extension/src/continueIdeClient.ts | 24 +- extension/src/terminal/terminalEmulator.ts | 301 +++--- 17 files changed, 277 insertions(+), 1312 deletions(-) create mode 100644 extension/esbuild.mjs create mode 100644 extension/react-app/src/components/ToggleErrorDiv.tsx (limited to 'continuedev/src') diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index d55e521b..b227570e 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -118,7 +118,7 @@ class Autopilot(ContinueBaseModel): f"\n{error_string}\n{e}") observation = InternalErrorObservation( - error=error_string) + error=error_string, title=e.title) step.hide = False except Exception as e: # Attach an InternalErrorObservation to the step and unhide it. @@ -128,7 +128,7 @@ class Autopilot(ContinueBaseModel): f"Error while running step: \n{error_string}\n{e}") observation = InternalErrorObservation( - error=error_string) + error=error_string, title=e.__repr__()) step.hide = False self._step_depth -= 1 diff --git a/continuedev/src/continuedev/core/main.py b/continuedev/src/continuedev/core/main.py index 17b30e96..33e25c93 100644 --- a/continuedev/src/continuedev/core/main.py +++ b/continuedev/src/continuedev/core/main.py @@ -181,10 +181,12 @@ class Context: class ContinueCustomException(Exception): + title: str message: str - def __init__(self, message: str): + def __init__(self, message: str, title: str = "Error while running step:"): self.message = message + self.title = title HistoryNode.update_forward_refs() diff --git a/continuedev/src/continuedev/core/observation.py b/continuedev/src/continuedev/core/observation.py index b6117236..126cf19e 100644 --- a/continuedev/src/continuedev/core/observation.py +++ b/continuedev/src/continuedev/core/observation.py @@ -36,4 +36,5 @@ class TextObservation(Observation): class InternalErrorObservation(Observation): + title: str error: str diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py index 690949f1..f4aa2b35 100644 --- a/continuedev/src/continuedev/core/sdk.py +++ b/continuedev/src/continuedev/core/sdk.py @@ -75,9 +75,9 @@ class ContinueSDK(AbstractContinueSDK): async def wait_for_user_confirmation(self, prompt: str): return await self.run_step(WaitForUserConfirmationStep(prompt=prompt)) - async def run(self, commands: Union[List[str], str], cwd: str = None, name: str = None, description: str = None): + async def run(self, commands: Union[List[str], str], cwd: str = None, name: str = None, description: str = None) -> Coroutine[str, None, None]: commands = commands if isinstance(commands, List) else [commands] - return await self.run_step(ShellCommandsStep(cmds=commands, cwd=cwd, description=description, **({'name': name} if name else {}))) + return (await self.run_step(ShellCommandsStep(cmds=commands, cwd=cwd, description=description, **({'name': name} if name else {})))).text async def edit_file(self, filename: str, prompt: str, name: str = None, description: str = None): filepath = await self._ensure_absolute_path(filename) @@ -131,5 +131,5 @@ class ContinueSDK(AbstractContinueSDK): # self.__autopilot.set_loading_message(message) raise NotImplementedError() - def raise_exception(self, message: str): - raise ContinueCustomException(message) + def raise_exception(self, message: str, title: str): + raise ContinueCustomException(message, title) diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py index 1206db0e..428ac9cc 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py @@ -22,7 +22,7 @@ class CreatePipelineRecipe(Step): - Load the data into a local DuckDB instance - Write a query to view the data""")) >> WaitForUserInputStep( - prompt="What API do you want to load data from?") + prompt="What API do you want to load data from? (e.g. weatherapi.com, chess.com)") ) await sdk.run_step( SetupPipelineStep(api_description=text_observation.text) >> diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py index 3c8277c0..9bee4c95 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py @@ -34,8 +34,7 @@ class SetupPipelineStep(Step): 'python3 -m venv env', 'source env/bin/activate', 'pip install dlt', - f'dlt init {source_name} duckdb', - 'Y', + f'dlt init {source_name} duckdb\n\rY', 'pip install -r requirements.txt' ], description=dedent(f"""\ Running the following commands: @@ -43,9 +42,8 @@ class SetupPipelineStep(Step): - `source env/bin/activate`: Activate the virtual environment - `pip install dlt`: Install dlt - `dlt init {source_name} duckdb`: Create a new dlt pipeline called {source_name} that loads data into a local DuckDB instance - - `pip install -r requirements.txt`: Install the Python dependencies for the pipeline""")) + - `pip install -r requirements.txt`: Install the Python dependencies for the pipeline"""), name="Setup Python environment") - await sdk.wait_for_user_confirmation("Wait for the commands to finish running, then press `Continue`") # editing the resource function to call the requested API await sdk.ide.highlightCode(RangeInFile(filepath=os.path.join(await sdk.ide.getWorkspaceDirectory(), filename), range=Range.from_shorthand(15, 0, 30, 0)), "#00ff0022") @@ -78,17 +76,12 @@ class ValidatePipelineStep(Step): # """))) # test that the API call works - - p = subprocess.run( - ['python3', f'{filename}'], capture_output=True, text=True, cwd=workspace_dir) - err = p.stderr + 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 err is not None and err != "": + if "Traceback" in output: sdk.raise_exception( - f"Error while running pipeline. Fix the resource function in {filename} and rerun this step: \n\n" + err) - - await sdk.run(f'python3 {filename}', name="Test the pipeline", description=f"Running python3 {filename} to test loading data from the API") + title="Error while running pipeline.\nFix the resource function in {filename} and rerun this step", description=output) # remove exit() from the main main function await sdk.edit_file( diff --git a/continuedev/src/continuedev/server/ide.py b/continuedev/src/continuedev/server/ide.py index 073e1dba..007eb2b4 100644 --- a/continuedev/src/continuedev/server/ide.py +++ b/continuedev/src/continuedev/server/ide.py @@ -76,6 +76,10 @@ class GetUserSecretResponse(BaseModel): value: str +class RunCommandResponse(BaseModel): + output: str + + T = TypeVar("T", bound=BaseModel) @@ -110,7 +114,7 @@ class IdeProtocolServer(AbstractIdeProtocolServer): fileEdits = list( map(lambda d: FileEditWithFullContents.parse_obj(d), data["fileEdits"])) self.onFileEdits(fileEdits) - elif message_type in ["highlightedCode", "openFiles", "readFile", "editFile", "workspaceDirectory", "getUserSecret"]: + elif message_type in ["highlightedCode", "openFiles", "readFile", "editFile", "workspaceDirectory", "getUserSecret", "runCommand"]: self.sub_queue.post(message_type, data) else: raise ValueError("Unknown message type", message_type) @@ -139,10 +143,8 @@ class IdeProtocolServer(AbstractIdeProtocolServer): "color": color }) - async def runCommand(self, command: str): - await self._send_json("runCommand", { - "command": command - }) + async def runCommand(self, command: str) -> str: + return (await self._send_and_receive_json({"command": command}, RunCommandResponse, "runCommand")).output async def showSuggestionsAndWait(self, suggestions: List[FileEdit]) -> bool: ids = [str(uuid.uuid4()) for _ in suggestions] diff --git a/continuedev/src/continuedev/server/ide_protocol.py b/continuedev/src/continuedev/server/ide_protocol.py index f42de68f..4622d6ff 100644 --- a/continuedev/src/continuedev/server/ide_protocol.py +++ b/continuedev/src/continuedev/server/ide_protocol.py @@ -88,5 +88,5 @@ class AbstractIdeProtocolServer(ABC): """Highlight code""" @abstractmethod - async def runCommand(self, command: str): + async def runCommand(self, command: str) -> str: """Run a command""" diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 99786b00..c6dc7c04 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -56,7 +56,9 @@ class ShellCommandsStep(Step): cwd = await sdk.ide.getWorkspaceDirectory() if self.cwd is None else self.cwd for cmd in self.cmds: - await sdk.ide.runCommand(cmd) + output = await sdk.ide.runCommand(cmd) + + return TextObservation(text=output) # process = subprocess.Popen( # '/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=cwd) @@ -205,7 +207,7 @@ class WaitForUserInputStep(Step): async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: self.description = self.prompt resp = await sdk.wait_for_user_input() - self._response = resp + self.description = f"{self.prompt}\n\n`{resp}`" return TextObservation(text=resp) diff --git a/extension/esbuild.mjs b/extension/esbuild.mjs new file mode 100644 index 00000000..bc1b3e5f --- /dev/null +++ b/extension/esbuild.mjs @@ -0,0 +1,14 @@ +import * as esbuild from "esbuild"; +// esbuild ./src/extension.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node +await esbuild.build({ + entryPoints: ["src/extension.ts"], + bundle: true, + outfile: "out/extension.js", + external: ["vscode"], + format: "cjs", + platform: "node", + sourcemap: true, + loader: { + ".node": "file", + }, +}); diff --git a/extension/package-lock.json b/extension/package-lock.json index fa09527e..a20be756 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -16,11 +16,10 @@ "@vitejs/plugin-react-swc": "^3.3.2", "axios": "^1.2.5", "highlight.js": "^11.7.0", - "octokit": "^2.0.11", "posthog-js": "^1.63.3", "react-markdown": "^8.0.7", "react-redux": "^8.0.5", - "strip-ansi": "^7.0.1", + "strip-ansi": "^7.1.0", "tailwindcss": "^3.3.2", "vite": "^4.3.9", "vscode-languageclient": "^8.0.2", @@ -1120,457 +1119,6 @@ "npm": ">=5.0.0" } }, - "node_modules/@octokit/app": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/@octokit/app/-/app-13.1.2.tgz", - "integrity": "sha512-Kf+h5sa1SOI33hFsuHvTsWj1jUrjp1x4MuiJBq7U/NicfEGa6nArPUoDnyfP/YTmcQ5cQ5yvOgoIBkbwPg6kzQ==", - "dependencies": { - "@octokit/auth-app": "^4.0.8", - "@octokit/auth-unauthenticated": "^3.0.0", - "@octokit/core": "^4.0.0", - "@octokit/oauth-app": "^4.0.7", - "@octokit/plugin-paginate-rest": "^6.0.0", - "@octokit/types": "^9.0.0", - "@octokit/webhooks": "^10.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/app/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/app/node_modules/@octokit/plugin-paginate-rest": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", - "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", - "dependencies": { - "@octokit/types": "^9.0.0" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=4" - } - }, - "node_modules/@octokit/app/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" - } - }, - "node_modules/@octokit/auth-app": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-4.0.8.tgz", - "integrity": "sha512-miI7y9FfS/fL1bSPsDaAfCGSxQ04iGLyisI2GA8N7P6eB6AkCOt+F1XXapJKRnAubQubvYF0dqxoTZYyKk93NQ==", - "dependencies": { - "@octokit/auth-oauth-app": "^5.0.0", - "@octokit/auth-oauth-user": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", - "@types/lru-cache": "^5.1.0", - "deprecation": "^2.3.1", - "lru-cache": "^6.0.0", - "universal-github-app-jwt": "^1.1.1", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-oauth-app": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-5.0.5.tgz", - "integrity": "sha512-UPX1su6XpseaeLVCi78s9droxpGtBWIgz9XhXAx9VXabksoF0MyI5vaa1zo1njyYt6VaAjFisC2A2Wchcu2WmQ==", - "dependencies": { - "@octokit/auth-oauth-device": "^4.0.0", - "@octokit/auth-oauth-user": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "@types/btoa-lite": "^1.0.0", - "btoa-lite": "^1.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-oauth-app/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/auth-oauth-app/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" - } - }, - "node_modules/@octokit/auth-oauth-device": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-4.0.3.tgz", - "integrity": "sha512-KPTx5nMntKjNZzzltO3X4T68v22rd7Cp/TcLJXQE2U8aXPcZ9LFuww9q9Q5WUNSu3jwi3lRwzfkPguRfz1R8Vg==", - "dependencies": { - "@octokit/oauth-methods": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^8.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-oauth-user": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-2.1.0.tgz", - "integrity": "sha512-TC2Mj8NkSy9uAnZLYX+FKB/IH6uDe+qYNzHzH8l13JlzsrTE7GKkcqtXdSGGN4tncyROAB4/KS5rDPRCEnWHlA==", - "dependencies": { - "@octokit/auth-oauth-device": "^4.0.0", - "@octokit/oauth-methods": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^8.0.0", - "btoa-lite": "^1.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", - "dependencies": { - "@octokit/types": "^9.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-token/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/auth-token/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" - } - }, - "node_modules/@octokit/auth-unauthenticated": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-3.0.4.tgz", - "integrity": "sha512-AT74XGBylcLr4lmUp1s6mjSUgphGdlse21Qjtv5DzpX1YOl5FXKwvNcZWESdhyBbpDT8VkVyLFqa/7a7eqpPNw==", - "dependencies": { - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-unauthenticated/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/auth-unauthenticated/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" - } - }, - "node_modules/@octokit/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz", - "integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==", - "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/core/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" - } - }, - "node_modules/@octokit/endpoint": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.4.tgz", - "integrity": "sha512-hXJP43VT2IrUxBCNIahta8qawpIzLvCjHLCuDDsdIPbd6+jPwsc3KGl/kdQ37mLd+sdiJm6c9qKI7k5CjE0Z9A==", - "dependencies": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/endpoint/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" - } - }, - "node_modules/@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", - "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/graphql/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" - } - }, - "node_modules/@octokit/oauth-app": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-4.2.0.tgz", - "integrity": "sha512-gyGclT77RQMkVUEW3YBeAKY+LBSc5u3eC9Wn/Uwt3WhuKuu9mrV18EnNpDqmeNll+mdV02yyBROU29Tlili6gg==", - "dependencies": { - "@octokit/auth-oauth-app": "^5.0.0", - "@octokit/auth-oauth-user": "^2.0.0", - "@octokit/auth-unauthenticated": "^3.0.0", - "@octokit/core": "^4.0.0", - "@octokit/oauth-authorization-url": "^5.0.0", - "@octokit/oauth-methods": "^2.0.0", - "@types/aws-lambda": "^8.10.83", - "fromentries": "^1.3.1", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/oauth-authorization-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-5.0.0.tgz", - "integrity": "sha512-y1WhN+ERDZTh0qZ4SR+zotgsQUE1ysKnvBt1hvDRB2WRzYtVKQjn97HEPzoehh66Fj9LwNdlZh+p6TJatT0zzg==", - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/oauth-methods": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-2.0.4.tgz", - "integrity": "sha512-RDSa6XL+5waUVrYSmOlYROtPq0+cfwppP4VaQY/iIei3xlFb0expH6YNsxNrZktcLhJWSpm9uzeom+dQrXlS3A==", - "dependencies": { - "@octokit/oauth-authorization-url": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", - "btoa-lite": "^1.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz", - "integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==", - "dependencies": { - "@octokit/types": "^8.0.0" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=4" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.8.1.tgz", - "integrity": "sha512-QrlaTm8Lyc/TbU7BL/8bO49vp+RZ6W3McxxmmQTgYxf2sWkO8ZKuj4dLhPNJD6VCUW1hetCmeIM0m6FTVpDiEg==", - "dependencies": { - "@octokit/types": "^8.1.1", - "deprecation": "^2.3.1" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-retry": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-4.0.4.tgz", - "integrity": "sha512-d7qGFLR3AH+WbNEDUvBPgMc7wRCxU40FZyNXFFqs8ISw75ZYS5/P3ScggzU13dCoY0aywYDxKugGstQTwNgppA==", - "dependencies": { - "@octokit/types": "^9.0.0", - "bottleneck": "^2.15.3" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" - } - }, - "node_modules/@octokit/plugin-throttling": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-4.3.2.tgz", - "integrity": "sha512-ZaCK599h3tzcoy0Jtdab95jgmD7X9iAk59E2E7hYKCAmnURaI4WpzwL9vckImilybUGrjY1JOWJapDs2N2D3vw==", - "dependencies": { - "@octokit/types": "^8.0.0", - "bottleneck": "^2.15.3" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": "^4.0.0" - } - }, - "node_modules/@octokit/request": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", - "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", - "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", - "dependencies": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/request-error/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" - } - }, - "node_modules/@octokit/types": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.2.1.tgz", - "integrity": "sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==", - "dependencies": { - "@octokit/openapi-types": "^14.0.0" - } - }, - "node_modules/@octokit/webhooks": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-10.7.0.tgz", - "integrity": "sha512-zZBbQMpXXnK/ki/utrFG/TuWv9545XCSLibfDTxrYqR1PmU6zel02ebTOrA7t5XIGHzlEOc/NgISUIBUe7pMFA==", - "dependencies": { - "@octokit/request-error": "^3.0.0", - "@octokit/webhooks-methods": "^3.0.0", - "@octokit/webhooks-types": "6.10.0", - "aggregate-error": "^3.1.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/webhooks-methods": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-3.0.2.tgz", - "integrity": "sha512-Vlnv5WBscf07tyAvfDbp7pTkMZUwk7z7VwEF32x6HqI+55QRwBTcT+D7DDjZXtad/1dU9E32x0HmtDlF9VIRaQ==", - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/webhooks-types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-6.10.0.tgz", - "integrity": "sha512-lDNv83BeEyxxukdQ0UttiUXawk9+6DkdjjFtm2GFED+24IQhTVaoSbwV9vWWKONyGLzRmCQqZmoEWkDhkEmPlw==" - }, "node_modules/@openapitools/openapi-generator-cli": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.6.0.tgz", @@ -2028,16 +1576,6 @@ "node": ">= 6" } }, - "node_modules/@types/aws-lambda": { - "version": "8.10.109", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.109.tgz", - "integrity": "sha512-/ME92FneNyXQzrAfcnQQlW1XkCZGPDlpi2ao1MJwecN+6SbeonKeggU8eybv1DfKli90FAVT1MlIZVXfwVuCyg==" - }, - "node_modules/@types/btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg==" - }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -2095,14 +1633,6 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", - "integrity": "sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", @@ -2117,11 +1647,6 @@ "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==", "dev": true }, - "node_modules/@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" - }, "node_modules/@types/mdast": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", @@ -2760,11 +2285,6 @@ } ] }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, "node_modules/big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", @@ -2830,11 +2350,6 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true }, - "node_modules/bottleneck": { - "version": "2.19.5", - "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", - "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==" - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2861,11 +2376,6 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "node_modules/btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==" - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -2898,11 +2408,6 @@ "node": "*" } }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, "node_modules/buffer-indexof-polyfill": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", @@ -3643,11 +3148,6 @@ "node": ">= 0.6" } }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -3787,14 +3287,6 @@ "wcwidth": ">=1.0.1" } }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -4443,25 +3935,6 @@ "node": ">= 6" } }, - "node_modules/fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -5201,14 +4674,6 @@ "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -5410,40 +4875,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", - "dependencies": { - "jws": "^3.2.2", - "lodash": "^4.17.21", - "ms": "^2.1.1", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "node_modules/keytar": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", @@ -6782,24 +6213,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/octokit": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/octokit/-/octokit-2.0.11.tgz", - "integrity": "sha512-Ivjapy5RXWvJfmZe0BvfMM2gnNi39rjheZV/s3SjICb7gfl83JWPDmBERe4f/l2czdRnj4NVIn4YO7Q737oLCg==", - "dependencies": { - "@octokit/app": "^13.1.1", - "@octokit/core": "^4.0.4", - "@octokit/oauth-app": "^4.0.6", - "@octokit/plugin-paginate-rest": "^5.0.0", - "@octokit/plugin-rest-endpoint-methods": "^6.0.0", - "@octokit/plugin-retry": "^4.0.3", - "@octokit/plugin-throttling": "^4.0.1", - "@octokit/types": "^8.0.0" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -7836,6 +7249,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -8119,9 +7533,9 @@ } }, "node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -8758,20 +8172,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/universal-github-app-jwt": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.1.1.tgz", - "integrity": "sha512-G33RTLrIBMFmlDV4u4CBF7dh71eWwykck4XgaxaIVeZKOYZRAAxvcGMRFTUclVY6xoUPQvO4Ne5wKGxYm/Yy9w==", - "dependencies": { - "@types/jsonwebtoken": "^9.0.0", - "jsonwebtoken": "^9.0.0" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -10018,394 +9418,6 @@ "node-fetch": "^2.6.1" } }, - "@octokit/app": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/@octokit/app/-/app-13.1.2.tgz", - "integrity": "sha512-Kf+h5sa1SOI33hFsuHvTsWj1jUrjp1x4MuiJBq7U/NicfEGa6nArPUoDnyfP/YTmcQ5cQ5yvOgoIBkbwPg6kzQ==", - "requires": { - "@octokit/auth-app": "^4.0.8", - "@octokit/auth-unauthenticated": "^3.0.0", - "@octokit/core": "^4.0.0", - "@octokit/oauth-app": "^4.0.7", - "@octokit/plugin-paginate-rest": "^6.0.0", - "@octokit/types": "^9.0.0", - "@octokit/webhooks": "^10.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/plugin-paginate-rest": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", - "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", - "requires": { - "@octokit/types": "^9.0.0" - } - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } - } - }, - "@octokit/auth-app": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-4.0.8.tgz", - "integrity": "sha512-miI7y9FfS/fL1bSPsDaAfCGSxQ04iGLyisI2GA8N7P6eB6AkCOt+F1XXapJKRnAubQubvYF0dqxoTZYyKk93NQ==", - "requires": { - "@octokit/auth-oauth-app": "^5.0.0", - "@octokit/auth-oauth-user": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", - "@types/lru-cache": "^5.1.0", - "deprecation": "^2.3.1", - "lru-cache": "^6.0.0", - "universal-github-app-jwt": "^1.1.1", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/auth-oauth-app": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-5.0.5.tgz", - "integrity": "sha512-UPX1su6XpseaeLVCi78s9droxpGtBWIgz9XhXAx9VXabksoF0MyI5vaa1zo1njyYt6VaAjFisC2A2Wchcu2WmQ==", - "requires": { - "@octokit/auth-oauth-device": "^4.0.0", - "@octokit/auth-oauth-user": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "@types/btoa-lite": "^1.0.0", - "btoa-lite": "^1.0.0", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } - } - }, - "@octokit/auth-oauth-device": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-4.0.3.tgz", - "integrity": "sha512-KPTx5nMntKjNZzzltO3X4T68v22rd7Cp/TcLJXQE2U8aXPcZ9LFuww9q9Q5WUNSu3jwi3lRwzfkPguRfz1R8Vg==", - "requires": { - "@octokit/oauth-methods": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^8.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/auth-oauth-user": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-2.1.0.tgz", - "integrity": "sha512-TC2Mj8NkSy9uAnZLYX+FKB/IH6uDe+qYNzHzH8l13JlzsrTE7GKkcqtXdSGGN4tncyROAB4/KS5rDPRCEnWHlA==", - "requires": { - "@octokit/auth-oauth-device": "^4.0.0", - "@octokit/oauth-methods": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^8.0.0", - "btoa-lite": "^1.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", - "requires": { - "@octokit/types": "^9.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } - } - }, - "@octokit/auth-unauthenticated": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-3.0.4.tgz", - "integrity": "sha512-AT74XGBylcLr4lmUp1s6mjSUgphGdlse21Qjtv5DzpX1YOl5FXKwvNcZWESdhyBbpDT8VkVyLFqa/7a7eqpPNw==", - "requires": { - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } - } - }, - "@octokit/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz", - "integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==", - "requires": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } - } - }, - "@octokit/endpoint": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.4.tgz", - "integrity": "sha512-hXJP43VT2IrUxBCNIahta8qawpIzLvCjHLCuDDsdIPbd6+jPwsc3KGl/kdQ37mLd+sdiJm6c9qKI7k5CjE0Z9A==", - "requires": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } - } - }, - "@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", - "requires": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } - } - }, - "@octokit/oauth-app": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-4.2.0.tgz", - "integrity": "sha512-gyGclT77RQMkVUEW3YBeAKY+LBSc5u3eC9Wn/Uwt3WhuKuu9mrV18EnNpDqmeNll+mdV02yyBROU29Tlili6gg==", - "requires": { - "@octokit/auth-oauth-app": "^5.0.0", - "@octokit/auth-oauth-user": "^2.0.0", - "@octokit/auth-unauthenticated": "^3.0.0", - "@octokit/core": "^4.0.0", - "@octokit/oauth-authorization-url": "^5.0.0", - "@octokit/oauth-methods": "^2.0.0", - "@types/aws-lambda": "^8.10.83", - "fromentries": "^1.3.1", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/oauth-authorization-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-5.0.0.tgz", - "integrity": "sha512-y1WhN+ERDZTh0qZ4SR+zotgsQUE1ysKnvBt1hvDRB2WRzYtVKQjn97HEPzoehh66Fj9LwNdlZh+p6TJatT0zzg==" - }, - "@octokit/oauth-methods": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-2.0.4.tgz", - "integrity": "sha512-RDSa6XL+5waUVrYSmOlYROtPq0+cfwppP4VaQY/iIei3xlFb0expH6YNsxNrZktcLhJWSpm9uzeom+dQrXlS3A==", - "requires": { - "@octokit/oauth-authorization-url": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", - "btoa-lite": "^1.0.0" - } - }, - "@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" - }, - "@octokit/plugin-paginate-rest": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz", - "integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==", - "requires": { - "@octokit/types": "^8.0.0" - } - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.8.1.tgz", - "integrity": "sha512-QrlaTm8Lyc/TbU7BL/8bO49vp+RZ6W3McxxmmQTgYxf2sWkO8ZKuj4dLhPNJD6VCUW1hetCmeIM0m6FTVpDiEg==", - "requires": { - "@octokit/types": "^8.1.1", - "deprecation": "^2.3.1" - } - }, - "@octokit/plugin-retry": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-4.0.4.tgz", - "integrity": "sha512-d7qGFLR3AH+WbNEDUvBPgMc7wRCxU40FZyNXFFqs8ISw75ZYS5/P3ScggzU13dCoY0aywYDxKugGstQTwNgppA==", - "requires": { - "@octokit/types": "^9.0.0", - "bottleneck": "^2.15.3" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } - } - }, - "@octokit/plugin-throttling": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-4.3.2.tgz", - "integrity": "sha512-ZaCK599h3tzcoy0Jtdab95jgmD7X9iAk59E2E7hYKCAmnURaI4WpzwL9vckImilybUGrjY1JOWJapDs2N2D3vw==", - "requires": { - "@octokit/types": "^8.0.0", - "bottleneck": "^2.15.3" - } - }, - "@octokit/request": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", - "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", - "requires": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", - "requires": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } - } - }, - "@octokit/types": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.2.1.tgz", - "integrity": "sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==", - "requires": { - "@octokit/openapi-types": "^14.0.0" - } - }, - "@octokit/webhooks": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-10.7.0.tgz", - "integrity": "sha512-zZBbQMpXXnK/ki/utrFG/TuWv9545XCSLibfDTxrYqR1PmU6zel02ebTOrA7t5XIGHzlEOc/NgISUIBUe7pMFA==", - "requires": { - "@octokit/request-error": "^3.0.0", - "@octokit/webhooks-methods": "^3.0.0", - "@octokit/webhooks-types": "6.10.0", - "aggregate-error": "^3.1.0" - } - }, - "@octokit/webhooks-methods": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-3.0.2.tgz", - "integrity": "sha512-Vlnv5WBscf07tyAvfDbp7pTkMZUwk7z7VwEF32x6HqI+55QRwBTcT+D7DDjZXtad/1dU9E32x0HmtDlF9VIRaQ==" - }, - "@octokit/webhooks-types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-6.10.0.tgz", - "integrity": "sha512-lDNv83BeEyxxukdQ0UttiUXawk9+6DkdjjFtm2GFED+24IQhTVaoSbwV9vWWKONyGLzRmCQqZmoEWkDhkEmPlw==" - }, "@openapitools/openapi-generator-cli": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.6.0.tgz", @@ -10658,16 +9670,6 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true }, - "@types/aws-lambda": { - "version": "8.10.109", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.109.tgz", - "integrity": "sha512-/ME92FneNyXQzrAfcnQQlW1XkCZGPDlpi2ao1MJwecN+6SbeonKeggU8eybv1DfKli90FAVT1MlIZVXfwVuCyg==" - }, - "@types/btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg==" - }, "@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -10725,14 +9727,6 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, - "@types/jsonwebtoken": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", - "integrity": "sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==", - "requires": { - "@types/node": "*" - } - }, "@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", @@ -10747,11 +9741,6 @@ "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==", "dev": true }, - "@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" - }, "@types/mdast": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", @@ -11217,11 +10206,6 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, - "before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, "big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", @@ -11277,11 +10261,6 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true }, - "bottleneck": { - "version": "2.19.5", - "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", - "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==" - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -11305,11 +10284,6 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==" - }, "buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -11325,11 +10299,6 @@ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, "buffer-indexof-polyfill": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", @@ -11862,11 +10831,6 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, "dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -11970,14 +10934,6 @@ "wcwidth": ">=1.0.1" } }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -12488,11 +11444,6 @@ "mime-types": "^2.1.12" } }, - "fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==" - }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -13030,11 +11981,6 @@ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - }, "is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -13183,36 +12129,6 @@ "universalify": "^2.0.0" } }, - "jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", - "requires": { - "jws": "^3.2.2", - "lodash": "^4.17.21", - "ms": "^2.1.1", - "semver": "^7.3.8" - } - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "keytar": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", @@ -14121,21 +13037,6 @@ "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "dev": true }, - "octokit": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/octokit/-/octokit-2.0.11.tgz", - "integrity": "sha512-Ivjapy5RXWvJfmZe0BvfMM2gnNi39rjheZV/s3SjICb7gfl83JWPDmBERe4f/l2czdRnj4NVIn4YO7Q737oLCg==", - "requires": { - "@octokit/app": "^13.1.1", - "@octokit/core": "^4.0.4", - "@octokit/oauth-app": "^4.0.6", - "@octokit/plugin-paginate-rest": "^5.0.0", - "@octokit/plugin-rest-endpoint-methods": "^6.0.0", - "@octokit/plugin-retry": "^4.0.3", - "@octokit/plugin-throttling": "^4.0.1", - "@octokit/types": "^8.0.0" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -14844,7 +13745,8 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -15042,9 +13944,9 @@ } }, "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "requires": { "ansi-regex": "^6.0.1" } @@ -15516,20 +14418,6 @@ "unist-util-is": "^5.0.0" } }, - "universal-github-app-jwt": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.1.1.tgz", - "integrity": "sha512-G33RTLrIBMFmlDV4u4CBF7dh71eWwykck4XgaxaIVeZKOYZRAAxvcGMRFTUclVY6xoUPQvO4Ne5wKGxYm/Yy9w==", - "requires": { - "@types/jsonwebtoken": "^9.0.0", - "jsonwebtoken": "^9.0.0" - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", diff --git a/extension/package.json b/extension/package.json index c834f402..598ae778 100644 --- a/extension/package.json +++ b/extension/package.json @@ -169,7 +169,7 @@ "scripts": { "vscode:prepublish": "npm run esbuild-base -- --minify", "esbuild-base": "rm -rf ./out && esbuild ./src/extension.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node", - "esbuild": "rm -rf ./out && npm run esbuild-base -- --sourcemap", + "esbuild": "rm -rf ./out && node esbuild.mjs", "esbuild-watch": "npm run esbuild-base -- --sourcemap --watch", "test-compile": "tsc -p ./", "clientgen": "rm -rf src/client/ && npx @openapitools/openapi-generator-cli generate -i ../schema/openapi.json -g typescript-fetch -o src/client/ --additional-properties=supportsES6=true,npmVersion=8.19.2,typescriptThreePlus=true", @@ -215,11 +215,10 @@ "@vitejs/plugin-react-swc": "^3.3.2", "axios": "^1.2.5", "highlight.js": "^11.7.0", - "octokit": "^2.0.11", "posthog-js": "^1.63.3", "react-markdown": "^8.0.7", "react-redux": "^8.0.5", - "strip-ansi": "^7.0.1", + "strip-ansi": "^7.1.0", "tailwindcss": "^3.3.2", "vite": "^4.3.9", "vscode-languageclient": "^8.0.2", diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index dab5a752..a150e370 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -22,6 +22,7 @@ import { HistoryNode } from "../../../schema/HistoryNode"; import ReactMarkdown from "react-markdown"; import ContinueButton from "./ContinueButton"; import InputAndButton from "./InputAndButton"; +import ToggleErrorDiv from "./ToggleErrorDiv"; interface StepContainerProps { historyNode: HistoryNode; @@ -170,13 +171,10 @@ function StepContainer(props: StepContainerProps) { )} {props.historyNode.observation?.error ? ( - <> - Error while running step: -
-
-                {props.historyNode.observation.error as string}
-              
- + ) : ( {props.historyNode.step.description as any} diff --git a/extension/react-app/src/components/ToggleErrorDiv.tsx b/extension/react-app/src/components/ToggleErrorDiv.tsx new file mode 100644 index 00000000..69112ef7 --- /dev/null +++ b/extension/react-app/src/components/ToggleErrorDiv.tsx @@ -0,0 +1,41 @@ +import React, { useState } from "react"; +import styled from "styled-components"; +import { defaultBorderRadius } from "."; + +// Should be a toggleable div with red border and light red background that displays a main message and detail inside + +interface ToggleErrorDivProps { + title: string; + error: string; +} + +const TopDiv = styled.div` + border: 1px solid red; + background-color: #ff000020; + padding: 8px; + + border-radius: ${defaultBorderRadius}; + cursor: pointer; +`; + +const ToggleErrorDiv = (props: ToggleErrorDivProps) => { + const [open, setOpen] = useState(false); + return ( + { + setOpen(!open); + }} + > +
+
+

+ {open ? "▼" : "▶"} {props.title} +

+
+
+ {open &&
{props.error}
} +
+ ); +}; + +export default ToggleErrorDiv; diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index c66172a9..308dfd57 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -43,6 +43,10 @@ function GUI(props: GUIProps) { // description: // "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py`", // }, + // observation: { + // error: + // "Traceback (most recent call last):\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/main.py\", line 7, in \n print(sum(first, second))\n ^^^^^^^^^^^^^^^^^^\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/sum.py\", line 2, in sum\n return a + b\n ~~^~~\nTypeError: unsupported operand type(s) for +: 'int' and 'str'", + // }, // output: [ // { // traceback: { diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index 25287d32..e84602f0 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -12,6 +12,7 @@ import { debugPanelWebview, setupDebugPanel } from "./debugPanel"; import { FileEditWithFullContents } from "../schema/FileEditWithFullContents"; import fs = require("fs"); import { WebsocketMessenger } from "./util/messenger"; +import { CapturedTerminal } from "./terminal/terminalEmulator"; class IdeProtocolClient { private messenger: WebsocketMessenger | null = null; @@ -100,7 +101,9 @@ class IdeProtocolClient { this.highlightCode(data.rangeInFile, data.color); break; case "runCommand": - this.runCommand(data.command); + this.messenger?.send("runCommand", { + output: await this.runCommand(data.command), + }); break; case "saveFile": this.saveFile(data.filepath); @@ -316,18 +319,15 @@ class IdeProtocolClient { return rangeInFiles; } - runCommand(command: string) { - if (vscode.window.terminals.length === 0) { - const terminal = vscode.window.createTerminal(); - terminal.show(); - terminal.sendText("bash", true); - terminal.sendText(command, true); - return; + private continueTerminal: CapturedTerminal | undefined; + + async runCommand(command: string) { + if (!this.continueTerminal) { + this.continueTerminal = new CapturedTerminal("Continue"); } - const terminal = vscode.window.terminals[0]; - terminal.show(); - terminal.sendText(command, true); - // But need to know when it's done executing... + + this.continueTerminal.show(); + return await this.continueTerminal.runCommand(command); } } diff --git a/extension/src/terminal/terminalEmulator.ts b/extension/src/terminal/terminalEmulator.ts index 6cf65970..8974b7e3 100644 --- a/extension/src/terminal/terminalEmulator.ts +++ b/extension/src/terminal/terminalEmulator.ts @@ -1,140 +1,161 @@ -// /* Terminal emulator - commented because node-pty is causing problems. */ - -// import * as vscode from "vscode"; -// import pty = require("node-pty"); -// import os = require("os"); -// import { extensionContext } from "../activation/activate"; -// import { debugPanelWebview } from "../debugPanel"; // Need to consider having multiple panels, where to store this state. -// import { -// CommandCaptureSnooper, -// PythonTracebackSnooper, -// TerminalSnooper, -// } from "./snoopers"; - -// export function tracebackToWebviewAction(traceback: string) { -// if (debugPanelWebview) { -// debugPanelWebview.postMessage({ -// type: "traceback", -// value: traceback, -// }); -// } else { -// vscode.commands -// .executeCommand("continue.openContinueGUI", extensionContext) -// .then(() => { -// // TODO: Waiting for the webview to load, but should add a hook to the onLoad message event. Same thing in autodebugTest command in commands.ts -// setTimeout(() => { -// debugPanelWebview?.postMessage({ -// type: "traceback", -// value: traceback, -// }); -// }, 500); -// }); -// } -// } - -// const DEFAULT_SNOOPERS = [ -// new PythonTracebackSnooper(tracebackToWebviewAction), -// new CommandCaptureSnooper((data: string) => { -// if (data.trim().startsWith("pytest ")) { -// let fileAndFunctionSpecifier = data.split(" ")[1]; -// vscode.commands.executeCommand( -// "continue.debugTest", -// fileAndFunctionSpecifier -// ); -// } -// }), -// ]; - -// // Whenever a user opens a terminal, replace it with ours -// vscode.window.onDidOpenTerminal((terminal) => { -// if (terminal.name != "Continue") { -// terminal.dispose(); -// openCapturedTerminal(); -// } -// }); - -// function getDefaultShell(): string { -// if (process.platform !== "win32") { -// return os.userInfo().shell; -// } -// switch (process.platform) { -// case "win32": -// return process.env.COMSPEC || "cmd.exe"; -// // case "darwin": -// // return process.env.SHELL || "/bin/zsh"; -// // default: -// // return process.env.SHELL || "/bin/sh"; -// } -// } - -// function getRootDir(): string | undefined { -// var isWindows = os.platform() === "win32"; -// let cwd = isWindows ? process.env.USERPROFILE : process.env.HOME; -// if ( -// vscode.workspace.workspaceFolders && -// vscode.workspace.workspaceFolders.length > 0 -// ) { -// cwd = vscode.workspace.workspaceFolders[0].uri.fsPath; -// } -// return cwd; -// } - -// export function openCapturedTerminal( -// snoopers: TerminalSnooper[] = DEFAULT_SNOOPERS -// ) { -// // If there is another existing, non-Continue terminal, delete it -// let terminals = vscode.window.terminals; -// for (let i = 0; i < terminals.length; i++) { -// if (terminals[i].name != "Continue") { -// terminals[i].dispose(); -// } -// } - -// let env = { ...(process.env as any) }; -// if (os.platform() !== "win32") { -// env["PATH"] += ":" + ["/opt/homebrew/bin", "/opt/homebrew/sbin"].join(":"); -// } - -// var ptyProcess = pty.spawn(getDefaultShell(), [], { -// name: "xterm-256color", -// cols: 160, // TODO: Get size of vscode terminal, and change with resize -// rows: 26, -// cwd: getRootDir(), -// env, -// useConpty: true, -// }); - -// const writeEmitter = new vscode.EventEmitter(); - -// ptyProcess.onData((data: any) => { -// // Let each of the snoopers see the new data -// for (let snooper of snoopers) { -// snooper.onData(data); -// } - -// // Pass data through to terminal -// writeEmitter.fire(data); -// }); -// process.on("exit", () => ptyProcess.kill()); - -// const newPty: vscode.Pseudoterminal = { -// onDidWrite: writeEmitter.event, -// open: () => {}, -// close: () => {}, -// handleInput: (data) => { -// for (let snooper of snoopers) { -// snooper.onWrite(data); -// } -// ptyProcess.write(data); -// }, -// }; -// const terminal = vscode.window.createTerminal({ -// name: "Continue", -// pty: newPty, -// }); -// terminal.show(); - -// setTimeout(() => { -// ptyProcess.write("clear\r"); -// }, 500); -// } +/* Terminal emulator - commented because node-pty is causing problems. */ + +import * as vscode from "vscode"; +import os = require("os"); +import stripAnsi from "strip-ansi"; + +function loadNativeModule(id: string): T | null { + try { + return require(`${vscode.env.appRoot}/node_modules.asar/${id}`); + } catch (err) { + // ignore + } + + try { + return require(`${vscode.env.appRoot}/node_modules/${id}`); + } catch (err) { + // ignore + } + + return null; +} + +const pty = loadNativeModule("node-pty"); + +function getDefaultShell(): string { + if (process.platform !== "win32") { + return os.userInfo().shell; + } + switch (process.platform) { + case "win32": + return process.env.COMSPEC || "cmd.exe"; + // case "darwin": + // return process.env.SHELL || "/bin/zsh"; + // default: + // return process.env.SHELL || "/bin/sh"; + } +} + +function getRootDir(): string | undefined { + const isWindows = os.platform() === "win32"; + let cwd = isWindows ? process.env.USERPROFILE : process.env.HOME; + if ( + vscode.workspace.workspaceFolders && + vscode.workspace.workspaceFolders.length > 0 + ) { + cwd = vscode.workspace.workspaceFolders[0].uri.fsPath; + } + return cwd; +} + +export class CapturedTerminal { + private readonly terminal: vscode.Terminal; + private readonly shellCmd: string; + private readonly ptyProcess: any; + + private shellPrompt: string | undefined = undefined; + private dataBuffer: string = ""; + + private onDataListeners: ((data: string) => void)[] = []; + + show() { + this.terminal.show(); + } + + private commandQueue: [string, (output: string) => void][] = []; + private hasRunCommand: boolean = false; + + private async waitForCommandToFinish() { + return new Promise((resolve, reject) => { + this.onDataListeners.push((data: any) => { + const strippedData = stripAnsi(data); + this.dataBuffer += strippedData; + const lines = this.dataBuffer.split("\n"); + if ( + lines.length > 0 && + lines[lines.length - 1].includes("bash-") && + lines[lines.length - 1].trim().endsWith("$") + ) { + resolve(this.dataBuffer); + this.dataBuffer = ""; + this.onDataListeners = []; + } + }); + }); + } + + async runCommand(command: string): Promise { + if (!this.hasRunCommand) { + this.hasRunCommand = true; + // Let the first bash- prompt appear and let python env be opened + await this.waitForCommandToFinish(); + } + + if (this.commandQueue.length === 0) { + return new Promise(async (resolve, reject) => { + this.commandQueue.push([command, resolve]); + + while (this.commandQueue.length > 0) { + const [command, resolve] = this.commandQueue.shift()!; + + this.terminal.sendText(command); + resolve(await this.waitForCommandToFinish()); + } + }); + } else { + return new Promise((resolve, reject) => { + this.commandQueue.push([command, resolve]); + }); + } + } + + private readonly writeEmitter: vscode.EventEmitter; + + constructor(terminalName: string) { + this.shellCmd = "bash"; // getDefaultShell(); + + const env = { ...(process.env as any) }; + if (os.platform() !== "win32") { + env.PATH += `:${["/opt/homebrew/bin", "/opt/homebrew/sbin"].join(":")}`; + } + + // Create the pseudo terminal + this.ptyProcess = pty.spawn(this.shellCmd, [], { + name: "xterm-256color", + cols: 160, // TODO: Get size of vscode terminal, and change with resize + rows: 26, + cwd: getRootDir(), + env, + useConpty: true, + }); + + this.writeEmitter = new vscode.EventEmitter(); + + this.ptyProcess.onData((data: any) => { + // Pass data through to terminal + this.writeEmitter.fire(data); + + for (let listener of this.onDataListeners) { + listener(data); + } + }); + + process.on("exit", () => this.ptyProcess.kill()); + + const newPty: vscode.Pseudoterminal = { + onDidWrite: this.writeEmitter.event, + open: () => {}, + close: () => {}, + handleInput: (data) => { + this.ptyProcess.write(data); + }, + }; + + // Create and clear the terminal + this.terminal = vscode.window.createTerminal({ + name: terminalName, + pty: newPty, + }); + this.terminal.show(); + } +} -- cgit v1.2.3-70-g09d2 From 0b7bf89141d2f7eba035c06bd848034c6d55fce6 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Wed, 7 Jun 2023 01:08:34 -0400 Subject: dlt stuff --- continuedev/src/continuedev/core/autopilot.py | 20 ++++++- continuedev/src/continuedev/core/main.py | 17 ++++-- continuedev/src/continuedev/core/policy.py | 8 +-- continuedev/src/continuedev/core/sdk.py | 4 +- .../recipes/CreatePipelineRecipe/steps.py | 64 +++++++++++++++++----- extension/package-lock.json | 4 +- extension/package.json | 2 +- .../react-app/src/components/StepContainer.tsx | 22 +++++--- extension/react-app/src/components/index.ts | 8 ++- extension/react-app/src/tabs/gui.tsx | 17 +++--- extension/src/continueIdeClient.ts | 1 + extension/src/terminal/terminalEmulator.ts | 5 +- 12 files changed, 124 insertions(+), 48 deletions(-) (limited to 'continuedev/src') diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index b227570e..5a6bd2e7 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -83,9 +83,9 @@ class Autopilot(ContinueBaseModel): _step_depth: int = 0 async def retry_at_index(self, index: int): - last_step = self.history.pop_last_step() + step = self.history.timeline[index].step.copy() await self.update_subscribers() - await self._run_singular_step(last_step) + await self._run_singular_step(step) async def _run_singular_step(self, step: "Step", is_future_step: bool = False) -> Coroutine[Observation, None, None]: capture_event( @@ -119,7 +119,17 @@ class Autopilot(ContinueBaseModel): observation = InternalErrorObservation( error=error_string, title=e.title) + + # 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 + + if e.with_step is not None: + await self._run_singular_step(e.with_step) + except Exception as e: # Attach an InternalErrorObservation to the step and unhide it. error_string = '\n\n'.join( @@ -129,7 +139,13 @@ class Autopilot(ContinueBaseModel): observation = InternalErrorObservation( error=error_string, title=e.__repr__()) + + # 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 self._step_depth -= 1 diff --git a/continuedev/src/continuedev/core/main.py b/continuedev/src/continuedev/core/main.py index 33e25c93..37d80de3 100644 --- a/continuedev/src/continuedev/core/main.py +++ b/continuedev/src/continuedev/core/main.py @@ -67,11 +67,16 @@ class History(ContinueBaseModel): return None return state.observation - def pop_last_step(self) -> Union[HistoryNode, None]: - if self.current_index < 0: + def pop_step(self, index: int = None) -> Union[HistoryNode, None]: + index = index if index is not None else self.current_index + if index < 0 or self.current_index < 0: return None - node = self.timeline.pop(self.current_index) - self.current_index -= 1 + + node = self.timeline.pop(index) + + if index <= self.current_index: + self.current_index -= 1 + return node.step @classmethod @@ -183,10 +188,12 @@ class Context: class ContinueCustomException(Exception): title: str message: str + with_step: Union[Step, None] - def __init__(self, message: str, title: str = "Error while running step:"): + def __init__(self, message: str, title: str = "Error while running step:", with_step: Union[Step, None] = None): self.message = message self.title = title + self.with_step = with_step HistoryNode.update_forward_refs() diff --git a/continuedev/src/continuedev/core/policy.py b/continuedev/src/continuedev/core/policy.py index 4934497d..91ae3c83 100644 --- a/continuedev/src/continuedev/core/policy.py +++ b/continuedev/src/continuedev/core/policy.py @@ -18,10 +18,10 @@ class DemoPolicy(Policy): # At the very start, run initial Steps spcecified in the config if history.get_current() is None: return ( - MessageStep(name="Welcome to Continue!", message="") >> - # SetupContinueWorkspaceStep() >> - # CreateCodebaseIndexChroma() >> - StepsOnStartupStep()) + # MessageStep(name="Welcome to Continue!", message="") >> + # SetupContinueWorkspaceStep() >> + # CreateCodebaseIndexChroma() >> + StepsOnStartupStep()) observation = history.get_current().observation if observation is not None and isinstance(observation, UserInputObservation): diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py index f4aa2b35..76caef02 100644 --- a/continuedev/src/continuedev/core/sdk.py +++ b/continuedev/src/continuedev/core/sdk.py @@ -131,5 +131,5 @@ class ContinueSDK(AbstractContinueSDK): # self.__autopilot.set_loading_message(message) raise NotImplementedError() - def raise_exception(self, message: str, title: str): - raise ContinueCustomException(message, title) + def raise_exception(self, message: str, title: str, with_step: Union[Step, None] = None): + raise ContinueCustomException(message, title, with_step) diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py index 9bee4c95..c32ae923 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py @@ -1,16 +1,19 @@ import os import subprocess from textwrap import dedent +import time from ...models.main import Range from ...models.filesystem import RangeInFile from ...steps.main import MessageStep from ...core.sdk import Models from ...core.observation import DictObservation, InternalErrorObservation -from ...models.filesystem_edit import AddFile +from ...models.filesystem_edit import AddFile, FileEdit from ...core.main import Step from ...core.sdk import ContinueSDK +AI_ASSISTED_STRING = "(✨ AI-Assisted ✨)" + class SetupPipelineStep(Step): hide: bool = True @@ -25,6 +28,8 @@ class SetupPipelineStep(Step): """) async def run(self, sdk: ContinueSDK): + sdk.context.set("api_description", self.api_description) + source_name = (await sdk.models.gpt35()).complete( f"Write a snake_case name for the data source described by {self.api_description}: ").strip() filename = f'{source_name}.py' @@ -45,14 +50,17 @@ class SetupPipelineStep(Step): - `pip install -r requirements.txt`: Install the Python dependencies for the pipeline"""), name="Setup Python environment") # editing the resource function to call the requested API - await sdk.ide.highlightCode(RangeInFile(filepath=os.path.join(await sdk.ide.getWorkspaceDirectory(), filename), range=Range.from_shorthand(15, 0, 30, 0)), "#00ff0022") + await sdk.ide.highlightCode(RangeInFile(filepath=os.path.join(await sdk.ide.getWorkspaceDirectory(), filename), range=Range.from_shorthand(15, 0, 29, 0)), "#00ff0022") + # sdk.set_loading_message("Writing code to call the API...") await sdk.edit_file( filename=filename, - prompt=f'Edit the resource function to call the API described by this: {self.api_description}', - name="Edit the resource function to call the API" + prompt=f'Edit the resource function to call the API described by this: {self.api_description}. Do not move or remove the exit() call in __main__.', + name=f"Edit the resource function to call the API {AI_ASSISTED_STRING}" ) + time.sleep(1) + # wait for user to put API key in secrets.toml await sdk.ide.setFileOpen(await sdk.ide.getWorkspaceDirectory() + "/.dlt/secrets.toml") await sdk.wait_for_user_confirmation("If this service requires an API key, please add it to the `secrets.toml` file and then press `Continue`") @@ -76,20 +84,50 @@ class ValidatePipelineStep(Step): # """))) # test that the API call works - output = await sdk.run(f'python3 {filename}', name="Test the pipeline", description=f"Running python3 {filename} to test loading data from the API") + 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: + 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"""\ + ```python + {file_content} + ``` + This above code is a dlt pipeline that loads data from an API. The function with the @resource decorator is responsible for calling the API and returning the data. While attempting to run the pipeline, the following error occurred: + + ```ascii + {output} + ``` + + This is a brief summary of the error followed by a suggestion on how it can be fixed by editing the resource function:""")) + + api_documentation_url = (await sdk.models.gpt35()).complete(dedent(f"""\ + The API I am trying to call is the '{sdk.context.get('api_description')}'. I tried calling it in the @resource function like this: + ```python + {file_content} + ``` + What is the URL for the API documentation that will help me learn how to make this call? Please format in markdown so I can click the link.""")) + sdk.raise_exception( - title="Error while running pipeline.\nFix the resource function in {filename} and rerun this step", description=output) + title=f"Error while running pipeline.\nFix the resource function in {filename} and rerun this step", message=output, with_step=MessageStep(name=f"Suggestion to solve error {AI_ASSISTED_STRING}", message=dedent(f"""\ + {suggestion} + + {api_documentation_url} + + After you've fixed the code, click the retry button at the top of the Validate Pipeline step above."""))) # remove exit() from the main main function - await sdk.edit_file( - filename=filename, - prompt='Remove exit() from the main function', - name="Remove early exit() from main function", - description="Remove the `exit()` call from the main function in the pipeline file so that the data is loaded into DuckDB" - ) + await sdk.run_step(MessageStep(name="Remove early exit() from main function", message="Remove the early exit() from the main function now that we are done testing and want the pipeline to load the data into DuckDB.")) + + contents = await sdk.ide.readFile(os.path.join(workspace_dir, filename)) + replacement = "\n".join( + list(filter(lambda line: line.strip() != "exit()", contents.split("\n")))) + await sdk.ide.applyFileSystemEdit(FileEdit( + filepath=os.path.join(workspace_dir, filename), + replacement=replacement, + range=Range.from_entire_file(contents) + )) # load the data into the DuckDB instance await sdk.run(f'python3 {filename}', name="Load data into DuckDB", description=f"Running python3 {filename} to load data into DuckDB") @@ -109,6 +147,6 @@ class ValidatePipelineStep(Step): print(row) ''') - query_filename = (await sdk.ide.getWorkspaceDirectory()) + "/query.py" + query_filename = os.path.join(workspace_dir, "query.py") await sdk.apply_filesystem_edit(AddFile(filepath=query_filename, content=tables_query_code), name="Add query.py file", description="Adding a file called `query.py` to the workspace that will run a test query on the DuckDB instance") await sdk.run('env/bin/python3 query.py', name="Run test query", description="Running `env/bin/python3 query.py` to test that the data was loaded into DuckDB as expected") diff --git a/extension/package-lock.json b/extension/package-lock.json index a20be756..0b0e063b 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.0.20", + "version": "0.0.23", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "continue", - "version": "0.0.20", + "version": "0.0.23", "license": "Apache-2.0", "dependencies": { "@electron/rebuild": "^3.2.10", diff --git a/extension/package.json b/extension/package.json index 598ae778..c979a435 100644 --- a/extension/package.json +++ b/extension/package.json @@ -14,7 +14,7 @@ "displayName": "Continue", "pricing": "Free", "description": "Refine code 10x faster", - "version": "0.0.20", + "version": "0.0.23", "publisher": "Continue", "engines": { "vscode": "^1.74.0" diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index a150e370..8ea54325 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -50,8 +50,9 @@ const StepContainerDiv = styled.div<{ open: boolean }>` /* padding: 8px; */ `; -const HeaderDiv = styled.div` - background-color: ${vscBackgroundTransparent}; +const HeaderDiv = styled.div<{ error: boolean }>` + background-color: ${(props) => + props.error ? "#522" : vscBackgroundTransparent}; display: grid; grid-template-columns: 1fr auto; align-items: center; @@ -124,17 +125,23 @@ function StepContainer(props: StepContainerProps) { > setOpen((prev) => !prev)} > - +

{open ? ( ) : ( )} - {props.historyNode.step.name as any} + {props.historyNode.observation?.title || + (props.historyNode.step.name as any)}

{/* { @@ -171,10 +178,9 @@ function StepContainer(props: StepContainerProps) { )} {props.historyNode.observation?.error ? ( - +
+              {props.historyNode.observation.error as string}
+            
) : ( {props.historyNode.step.description as any} diff --git a/extension/react-app/src/components/index.ts b/extension/react-app/src/components/index.ts index ac5faa41..4966f3e8 100644 --- a/extension/react-app/src/components/index.ts +++ b/extension/react-app/src/components/index.ts @@ -98,17 +98,21 @@ export const Loader = styled.div` export const GradientBorder = styled.div<{ borderWidth?: string; borderRadius?: string; + borderColor?: string; }>` border-radius: ${(props) => props.borderRadius || "0"}; padding-top: ${(props) => props.borderWidth || "1px"}; padding-bottom: ${(props) => props.borderWidth || "1px"}; - background: linear-gradient( + background: ${(props) => + props.borderColor + ? props.borderColor + : `linear-gradient( 101.79deg, #12887a 0%, #87245c 37.64%, #e12637 65.98%, #ffb215 110.45% - ); + )`}; `; export const MainContainerWithBorder = styled.div<{ borderWidth?: string }>` diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 308dfd57..5c75579b 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -44,6 +44,7 @@ function GUI(props: GUIProps) { // "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py`", // }, // observation: { + // title: "ERROR FOUND", // error: // "Traceback (most recent call last):\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/main.py\", line 7, in \n print(sum(first, second))\n ^^^^^^^^^^^^^^^^^^\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/sum.py\", line 2, in sum\n return a + b\n ~~^~~\nTypeError: unsupported operand type(s) for +: 'int' and 'str'", // }, @@ -228,9 +229,9 @@ function GUI(props: GUIProps) { setUserInputQueue((queue) => { return [...queue, input]; }); - mainTextInputRef.current.value = ""; - mainTextInputRef.current.style.height = ""; } + mainTextInputRef.current.value = ""; + mainTextInputRef.current.style.height = ""; } setWaitingForSteps(true); @@ -307,13 +308,15 @@ function GUI(props: GUIProps) { }} rows={1} onChange={() => { - let textarea = mainTextInputRef.current!; + const textarea = mainTextInputRef.current!; textarea.style.height = ""; /* Reset the height*/ - textarea.style.height = - Math.min(textarea.scrollHeight - 15, 500) + "px"; + textarea.style.height = `${Math.min( + textarea.scrollHeight - 15, + 500 + )}px`; }} - >
- + /> + ); } diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index e84602f0..bbaf5f08 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -142,6 +142,7 @@ class IdeProtocolClient { editor.setDecorations( vscode.window.createTextEditorDecorationType({ backgroundColor: color, + isWholeLine: true, }), [range] ); diff --git a/extension/src/terminal/terminalEmulator.ts b/extension/src/terminal/terminalEmulator.ts index 8974b7e3..67b47e2f 100644 --- a/extension/src/terminal/terminalEmulator.ts +++ b/extension/src/terminal/terminalEmulator.ts @@ -73,8 +73,9 @@ export class CapturedTerminal { const lines = this.dataBuffer.split("\n"); if ( lines.length > 0 && - lines[lines.length - 1].includes("bash-") && - lines[lines.length - 1].trim().endsWith("$") + (lines[lines.length - 1].includes("bash-") || + lines[lines.length - 1].includes("(main)")) && + lines[lines.length - 1].includes("$") ) { resolve(this.dataBuffer); this.dataBuffer = ""; -- cgit v1.2.3-70-g09d2 From 81b38be5b1199e95534b99168465a8cfcef7e1cb Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Wed, 7 Jun 2023 14:42:22 -0400 Subject: Use gpt by default, with prefix/suffixes --- continuedev/src/continuedev/core/policy.py | 2 +- continuedev/src/continuedev/core/sdk.py | 12 +-- .../recipes/CreatePipelineRecipe/steps.py | 9 +- continuedev/src/continuedev/steps/core/core.py | 95 +++++++++++++--------- continuedev/src/continuedev/steps/main.py | 17 +--- 5 files changed, 74 insertions(+), 61 deletions(-) (limited to 'continuedev/src') diff --git a/continuedev/src/continuedev/core/policy.py b/continuedev/src/continuedev/core/policy.py index 91ae3c83..8aea8de7 100644 --- a/continuedev/src/continuedev/core/policy.py +++ b/continuedev/src/continuedev/core/policy.py @@ -38,7 +38,7 @@ class DemoPolicy(Policy): return EditFileChroma(request=" ".join(observation.user_input.split(" ")[1:])) elif "/step" in observation.user_input: return ContinueStepStep(prompt=" ".join(observation.user_input.split(" ")[1:])) - return StarCoderEditHighlightedCodeStep(user_input=observation.user_input) + return EditHighlightedCodeStep(user_input=observation.user_input) state = history.get_current() diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py index 76caef02..51faadf2 100644 --- a/continuedev/src/continuedev/core/sdk.py +++ b/continuedev/src/continuedev/core/sdk.py @@ -2,11 +2,12 @@ from abc import ABC, abstractmethod from typing import Coroutine, Union import os +from ..steps.core.core import Gpt35EditCodeStep +from ..models.main import Range from .abstract_sdk import AbstractContinueSDK from .config import ContinueConfig, load_config from ..models.filesystem_edit import FileEdit, FileSystemEdit, AddFile, DeleteFile, AddDirectory, DeleteDirectory from ..models.filesystem import RangeInFile -from ..libs.llm import LLM from ..libs.llm.hf_inference_api import HuggingFaceInferenceAPI from ..libs.llm.openai import OpenAI from .observation import Observation @@ -79,14 +80,15 @@ class ContinueSDK(AbstractContinueSDK): commands = commands if isinstance(commands, List) else [commands] return (await self.run_step(ShellCommandsStep(cmds=commands, cwd=cwd, description=description, **({'name': name} if name else {})))).text - async def edit_file(self, filename: str, prompt: str, name: str = None, description: str = None): + async def edit_file(self, filename: str, prompt: str, name: str = None, description: str = None, range: Range = None): filepath = await self._ensure_absolute_path(filename) await self.ide.setFileOpen(filepath) contents = await self.ide.readFile(filepath) - await self.run_step(EditCodeStep( - range_in_files=[RangeInFile.from_entire_file(filepath, 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', + await self.run_step(Gpt35EditCodeStep( + range_in_files=[RangeInFile(filepath=filename, range=range) if range is not None else RangeInFile.from_entire_file( + filepath, contents)], + user_input=prompt, description=description, **({'name': name} if name else {}) )) diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py index c32ae923..511abd1f 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py @@ -39,7 +39,7 @@ class SetupPipelineStep(Step): 'python3 -m venv env', 'source env/bin/activate', 'pip install dlt', - f'dlt init {source_name} duckdb\n\rY', + f'dlt --non-interactive init {source_name} duckdb', 'pip install -r requirements.txt' ], description=dedent(f"""\ Running the following commands: @@ -50,10 +50,12 @@ class SetupPipelineStep(Step): - `pip install -r requirements.txt`: Install the Python dependencies for the pipeline"""), name="Setup Python environment") # editing the resource function to call the requested API - await sdk.ide.highlightCode(RangeInFile(filepath=os.path.join(await sdk.ide.getWorkspaceDirectory(), filename), range=Range.from_shorthand(15, 0, 29, 0)), "#00ff0022") + resource_function_range = Range.from_shorthand(15, 0, 29, 0) + await sdk.ide.highlightCode(RangeInFile(filepath=os.path.join(await sdk.ide.getWorkspaceDirectory(), filename), range=resource_function_range), "#00ff0022") # sdk.set_loading_message("Writing code to call the API...") await sdk.edit_file( + range=resource_function_range, filename=filename, prompt=f'Edit the resource function to call the API described by this: {self.api_description}. Do not move or remove the exit() call in __main__.', name=f"Edit the resource function to call the API {AI_ASSISTED_STRING}" @@ -144,8 +146,7 @@ class ValidatePipelineStep(Step): # print table names for row in rows: - print(row) - ''') + print(row)''') query_filename = os.path.join(workspace_dir, "query.py") await sdk.apply_filesystem_edit(AddFile(filepath=query_filename, content=tables_query_code), name="Add query.py file", description="Adding a file called `query.py` to the workspace that will run a test query on the DuckDB instance") diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index c6dc7c04..413bc195 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -4,7 +4,7 @@ from textwrap import dedent from typing import Coroutine, List, Union from ...libs.llm.prompt_utils import MarkdownStyleEncoderDecoder -from ...models.filesystem_edit import EditDiff, FileEditWithFullContents, FileSystemEdit +from ...models.filesystem_edit import EditDiff, FileEdit, FileEditWithFullContents, FileSystemEdit from ...models.filesystem import FileSystem, RangeInFile, RangeInFileWithContents from ...core.observation import Observation, TextObservation, TracebackObservation, UserInputObservation from ...core.main import Step, SequentialStep @@ -74,26 +74,48 @@ class ShellCommandsStep(Step): # return None -class EditCodeStep(Step): - # Might make an even more specific atomic step, which is "apply file edit" +class Gpt35EditCodeStep(Step): + user_input: str 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 + name: str = "Editing Code" + hide = False + _prompt: str = dedent("""\ + Take the file prefix and suffix into account, but only rewrite the commit before as specified in the commit message. Here's an example: + + + a = 5 + b = 4 + + + + def mul(a, b): + return a * b + + def sum(): + return a + b + + Make a and b parameters of sum + + def sum(a, b): + return a + b + <|endoftext|> + + Now complete the real thing: + + + {file_prefix} + + {file_suffix} + + {code} + + {user_request} + """) + + _prompt_and_completion: str = "" async def describe(self, models: Models) -> 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 (await models.gpt35()).complete(dedent(f"""{self._prompt}{self._completion} - - Maximally concise summary of changes in bullet points (can use markdown): - """)) + return (await models.gpt35()).complete(f"{self._prompt_and_completion}\n\nPlease give brief a description of the changes made above using markdown bullet points:") async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: rif_with_contents = [] @@ -101,28 +123,27 @@ class EditCodeStep(Step): 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 = (await sdk.models.gpt35()).complete(prompt) - # Temporarily doing this to generate description. - self._prompt = prompt - self._completion = completion + rif_dict = {} + for rif in rif_with_contents: + rif_dict[rif.filepath] = rif.contents - file_edits = enc_dec.decode(completion) + for rif in rif_with_contents: + full_file_contents = await sdk.ide.readFile(rif.filepath) + segs = full_file_contents.split(rif.contents) + prompt = self._prompt.format( + code=rif.contents, user_request=self.user_input, file_prefix=segs[0], file_suffix=segs[1]) - self._edit_diffs = [] - for file_edit in file_edits: - diff = await sdk.apply_filesystem_edit(file_edit) - self._edit_diffs.append(diff) + completion = str((await sdk.models.gpt35()).complete(prompt)) + eot_token = "<|endoftext|>" + completion = completion.removesuffix(eot_token) - for filepath in set([file_edit.filepath for file_edit in file_edits]): - await sdk.ide.saveFile(filepath) - await sdk.ide.setFileOpen(filepath) + self._prompt_and_completion += prompt + completion - return None + await sdk.ide.applyFileSystemEdit( + FileEdit(filepath=rif.filepath, range=rif.range, replacement=completion)) + await sdk.ide.saveFile(rif.filepath) + await sdk.ide.setFileOpen(rif.filepath) class EditFileStep(Step): @@ -135,10 +156,10 @@ class EditFileStep(Step): async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: file_contents = await sdk.ide.readFile(self.filepath) - await sdk.run_step(EditCodeStep( + await sdk.run_step(Gpt35EditCodeStep( range_in_files=[RangeInFile.from_entire_file( self.filepath, file_contents)], - prompt=self.prompt + user_input=self.prompt )) diff --git a/continuedev/src/continuedev/steps/main.py b/continuedev/src/continuedev/steps/main.py index da0fc8d2..69c98bd4 100644 --- a/continuedev/src/continuedev/steps/main.py +++ b/continuedev/src/continuedev/steps/main.py @@ -15,7 +15,7 @@ from ..core.main import Step from ..core.sdk import ContinueSDK, Models from ..core.observation import Observation import subprocess -from .core.core import EditCodeStep +from .core.core import Gpt35EditCodeStep class SetupContinueWorkspaceStep(Step): @@ -255,19 +255,9 @@ class StarCoderEditHighlightedCodeStep(Step): class EditHighlightedCodeStep(Step): user_input: str hide = True - _prompt: str = dedent("""Below is the code before changes: - -{code} - -This is the user request: - -{user_input} - -This is the code after being changed to perfectly satisfy the user request: - """) async def describe(self, models: Models) -> Coroutine[str, None, None]: - return "Editing highlighted code" + return "Editing code" async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: range_in_files = await sdk.ide.getHighlightedCode() @@ -281,8 +271,7 @@ This is the code after being changed to perfectly satisfy the user request: range_in_files = [RangeInFile.from_entire_file( filepath, content) for filepath, content in contents.items()] - await sdk.run_step(EditCodeStep( - range_in_files=range_in_files, prompt=self._prompt.format(code="{code}", user_input=self.user_input))) + await sdk.run_step(Gpt35EditCodeStep(user_input=self.user_input, range_in_files=range_in_files)) class FindCodeStep(Step): -- cgit v1.2.3-70-g09d2