summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--continuedev/src/continuedev/core/autopilot.py20
-rw-r--r--continuedev/src/continuedev/core/main.py17
-rw-r--r--continuedev/src/continuedev/core/policy.py8
-rw-r--r--continuedev/src/continuedev/core/sdk.py4
-rw-r--r--continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py64
-rw-r--r--extension/package-lock.json4
-rw-r--r--extension/package.json2
-rw-r--r--extension/react-app/src/components/StepContainer.tsx22
-rw-r--r--extension/react-app/src/components/index.ts8
-rw-r--r--extension/react-app/src/tabs/gui.tsx17
-rw-r--r--extension/src/continueIdeClient.ts1
-rw-r--r--extension/src/terminal/terminalEmulator.ts5
12 files changed, 124 insertions, 48 deletions
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) {
>
<StepContainerDiv open={open}>
<GradientBorder
+ borderColor={
+ props.historyNode.observation?.error ? "#f00" : undefined
+ }
className="overflow-hidden cursor-pointer"
onClick={() => setOpen((prev) => !prev)}
>
- <HeaderDiv>
+ <HeaderDiv
+ error={props.historyNode.observation?.error ? true : false}
+ >
<h4 className="m-2">
{open ? (
<ChevronDown size="1.4em" />
) : (
<ChevronRight size="1.4em" />
)}
- {props.historyNode.step.name as any}
+ {props.historyNode.observation?.title ||
+ (props.historyNode.step.name as any)}
</h4>
{/* <HeaderButton
onClick={(e) => {
@@ -171,10 +178,9 @@ function StepContainer(props: StepContainerProps) {
)}
{props.historyNode.observation?.error ? (
- <ToggleErrorDiv
- title={"Error while running step:"}
- error={props.historyNode.observation.error as string}
- />
+ <pre className="overflow-x-scroll">
+ {props.historyNode.observation.error as string}
+ </pre>
) : (
<ReactMarkdown key={1} className="overflow-scroll">
{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 <module>\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`;
}}
- ></MainTextInput>
- <ContinueButton onClick={onMainTextInput}></ContinueButton>
+ />
+ <ContinueButton onClick={onMainTextInput} />
</TopGUIDiv>
);
}
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 = "";