diff options
| -rw-r--r-- | continuedev/src/continuedev/core/autopilot.py | 10 | ||||
| -rw-r--r-- | continuedev/src/continuedev/libs/util/calculate_diff.py | 14 | ||||
| -rw-r--r-- | continuedev/src/continuedev/server/gui.py | 10 | ||||
| -rw-r--r-- | continuedev/src/continuedev/server/gui_protocol.py | 8 | ||||
| -rw-r--r-- | continuedev/src/continuedev/steps/core/core.py | 2 | ||||
| -rw-r--r-- | extension/react-app/src/components/StepContainer.tsx | 44 | ||||
| -rw-r--r-- | extension/react-app/src/components/index.ts | 18 | ||||
| -rw-r--r-- | extension/react-app/src/hooks/ContinueGUIClientProtocol.ts | 6 | ||||
| -rw-r--r-- | extension/react-app/src/hooks/useContinueGUIProtocol.ts | 8 | ||||
| -rw-r--r-- | extension/react-app/src/tabs/gui.tsx | 272 | 
10 files changed, 245 insertions, 147 deletions
diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index c979d53a..1642003c 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -40,6 +40,12 @@ class Autopilot(ContinueBaseModel):      def get_full_state(self) -> FullState:          return FullState(history=self.history, active=self._active, user_input_queue=self._main_user_input_queue) +    async def clear_history(self): +        self.history = History.from_empty() +        self._main_user_input_queue = [] +        self._active = False +        await self.update_subscribers() +      def on_update(self, callback: Coroutine["FullState", None, None]):          """Subscribe to changes to state"""          self._on_update_callbacks.append(callback) @@ -88,6 +94,10 @@ class Autopilot(ContinueBaseModel):      async def retry_at_index(self, index: int):          self._retry_queue.post(str(index), None) +    async def delete_at_index(self, index: int): +        self.history.timeline[index].step.hide = True +        await self.update_subscribers() +      async def _run_singular_step(self, step: "Step", is_future_step: bool = False) -> Coroutine[Observation, None, None]:          capture_event(              'step run', {'step_name': step.name, 'params': step.dict()}) diff --git a/continuedev/src/continuedev/libs/util/calculate_diff.py b/continuedev/src/continuedev/libs/util/calculate_diff.py index d778891b..ff0a135f 100644 --- a/continuedev/src/continuedev/libs/util/calculate_diff.py +++ b/continuedev/src/continuedev/libs/util/calculate_diff.py @@ -67,6 +67,20 @@ def calculate_diff(filepath: str, original: str, updated: str) -> List[FileEdit]  def calculate_diff2(filepath: str, original: str, updated: str) -> List[FileEdit]: +    # original_lines = original.splitlines() +    # updated_lines = updated.splitlines() +    # offset = 0 +    # while len(original_lines) and len(updated_lines) and original_lines[0] == updated_lines[0]: +    #     original_lines = original_lines[1:] +    #     updated_lines = updated_lines[1:] + +    # while len(original_lines) and len(updated_lines) and original_lines[-1] == updated_lines[-1]: +    #     original_lines = original_lines[:-1] +    #     updated_lines = updated_lines[:-1] + +    # original = "\n".join(original_lines) +    # updated = "\n".join(updated_lines) +      edits = []      max_iterations = 1000      i = 0 diff --git a/continuedev/src/continuedev/server/gui.py b/continuedev/src/continuedev/server/gui.py index b873a88f..e8b52004 100644 --- a/continuedev/src/continuedev/server/gui.py +++ b/continuedev/src/continuedev/server/gui.py @@ -77,6 +77,10 @@ class GUIProtocolServer(AbstractGUIProtocolServer):                  self.on_reverse_to_index(data["index"])              elif message_type == "retry_at_index":                  self.on_retry_at_index(data["index"]) +            elif message_type == "clear_history": +                self.on_clear_history() +            elif message_type == "delete_at_index": +                self.on_delete_at_index(data["index"])          except Exception as e:              print(e) @@ -106,6 +110,12 @@ class GUIProtocolServer(AbstractGUIProtocolServer):          asyncio.create_task(              self.session.autopilot.retry_at_index(index)) +    def on_clear_history(self): +        asyncio.create_task(self.session.autopilot.clear_history()) + +    def on_delete_at_index(self, index: int): +        asyncio.create_task(self.session.autopilot.delete_at_index(index)) +  @router.websocket("/ws")  async def websocket_endpoint(websocket: WebSocket, session: Session = Depends(websocket_session)): diff --git a/continuedev/src/continuedev/server/gui_protocol.py b/continuedev/src/continuedev/server/gui_protocol.py index 287f9e3b..889c6761 100644 --- a/continuedev/src/continuedev/server/gui_protocol.py +++ b/continuedev/src/continuedev/server/gui_protocol.py @@ -30,3 +30,11 @@ class AbstractGUIProtocolServer(ABC):      @abstractmethod      def on_retry_at_index(self, index: int):          """Called when the user requests a retry at a previous index""" + +    @abstractmethod +    def on_clear_history(self): +        """Called when the user requests to clear the history""" + +    @abstractmethod +    def on_delete_at_index(self, index: int): +        """Called when the user requests to delete a step at a given index""" diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 4288ffd2..dacf0e7b 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -193,7 +193,7 @@ class Gpt35EditCodeStep(Step):                  edit.range.end.line += rif.range.start.line                  edit.range.end.character += rif.range.start.character if edit.range.end.line == 0 else 0 -                for line in range(edit.range.start.line, edit.range.end.line + 1): +                for line in range(edit.range.start.line, edit.range.end.line + 1 + len(edit.replacement.splitlines()) - (edit.range.end.line - edit.range.start.line + 1)):                      lines_to_highlight.add(line)                  await sdk.ide.applyFileSystemEdit(edit) diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index fb0143b5..2d85b4f0 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -7,6 +7,7 @@ import {    vscBackground,    GradientBorder,    vscBackgroundTransparent, +  HeaderButton,  } from ".";  import { RangeInFile, FileEdit } from "../../../src/client";  import CodeBlock from "./CodeBlock"; @@ -15,7 +16,7 @@ import SubContainer from "./SubContainer";  import {    ChevronDown,    ChevronRight, -  Backward, +  XMark,    ArrowPath,  } from "@styled-icons/heroicons-outline";  import { HistoryNode } from "../../../schema/HistoryNode"; @@ -31,6 +32,7 @@ interface StepContainerProps {    onRefinement: (input: string) => void;    onUserInput: (input: string) => void;    onRetry: () => void; +  onDelete: () => void;    open?: boolean;  } @@ -54,8 +56,10 @@ const HeaderDiv = styled.div<{ error: boolean }>`    background-color: ${(props) =>      props.error ? "#522" : vscBackgroundTransparent};    display: grid; -  grid-template-columns: 1fr auto; +  grid-template-columns: 1fr auto auto; +  grid-gap: 8px;    align-items: center; +  padding-right: 8px;  `;  const ContentDiv = styled.div` @@ -64,20 +68,6 @@ const ContentDiv = styled.div`    background-color: ${vscBackground};  `; -const HeaderButton = styled.button` -  background-color: transparent; -  border: 1px solid white; -  border-radius: ${defaultBorderRadius}; -  padding: 2px; -  cursor: pointer; -  color: white; - -  &:hover { -    background-color: white; -    color: black; -  } -`; -  const OnHoverDiv = styled.div`    text-align: center;    padding: 10px; @@ -161,18 +151,28 @@ function StepContainer(props: StepContainerProps) {                <Backward size="1.6em" onClick={props.onReverse}></Backward>              </HeaderButton> */} -            {props.historyNode.observation?.error ? ( +            <>                <HeaderButton                  onClick={(e) => {                    e.stopPropagation(); -                  props.onRetry(); +                  props.onDelete();                  }}                > -                <ArrowPath size="1.6em" onClick={props.onRetry}></ArrowPath> +                <XMark size="1.6em" onClick={props.onDelete} />                </HeaderButton> -            ) : ( -              <></> -            )} +              {props.historyNode.observation?.error ? ( +                <HeaderButton +                  onClick={(e) => { +                    e.stopPropagation(); +                    props.onRetry(); +                  }} +                > +                  <ArrowPath size="1.6em" onClick={props.onRetry} /> +                </HeaderButton> +              ) : ( +                <></> +              )} +            </>            </HeaderDiv>          </GradientBorder>          <ContentDiv hidden={!open}> diff --git a/extension/react-app/src/components/index.ts b/extension/react-app/src/components/index.ts index 4966f3e8..525989af 100644 --- a/extension/react-app/src/components/index.ts +++ b/extension/react-app/src/components/index.ts @@ -143,3 +143,21 @@ export const appear = keyframes`          transform: translateY(0px);      }  `; + +export const HeaderButton = styled.button` +  background-color: transparent; +  border: 1px solid white; +  border-radius: ${defaultBorderRadius}; +  cursor: pointer; +  color: white; + +  &:hover { +    background-color: white; +    color: black; +  } +  display: flex; +  align-items: center; +  justify-content: center; +  gap: 4px; +  padding: 1px; +`; diff --git a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts index 18a91de7..71303c70 100644 --- a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts +++ b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts @@ -8,6 +8,12 @@ abstract class AbstractContinueGUIClientProtocol {    abstract sendStepUserInput(input: string, index: number): void;    abstract onStateUpdate(state: any): void; + +  abstract sendClear(): void; + +  abstract retryAtIndex(index: number): void; + +  abstract deleteAtIndex(index: number): void;  }  export default AbstractContinueGUIClientProtocol; diff --git a/extension/react-app/src/hooks/useContinueGUIProtocol.ts b/extension/react-app/src/hooks/useContinueGUIProtocol.ts index f27895fb..a8e28fc5 100644 --- a/extension/react-app/src/hooks/useContinueGUIProtocol.ts +++ b/extension/react-app/src/hooks/useContinueGUIProtocol.ts @@ -45,9 +45,17 @@ class ContinueGUIClientProtocol extends AbstractContinueGUIClientProtocol {      });    } +  sendClear() { +    this.messenger.send("clear_history", {}); +  } +    retryAtIndex(index: number) {      this.messenger.send("retry_at_index", { index });    } + +  deleteAtIndex(index: number) { +    this.messenger.send("delete_at_index", { index }); +  }  }  export default ContinueGUIClientProtocol; diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 9f7e651f..cb7a5440 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -4,6 +4,7 @@ import {    vscBackground,    Loader,    MainTextInput, +  HeaderButton,  } from "../components";  import ContinueButton from "../components/ContinueButton";  import { useCallback, useEffect, useRef, useState } from "react"; @@ -11,7 +12,7 @@ import { History } from "../../../schema/History";  import { HistoryNode } from "../../../schema/HistoryNode";  import StepContainer from "../components/StepContainer";  import useContinueGUIProtocol from "../hooks/useWebsocket"; - +import { Trash } from "@styled-icons/heroicons-outline";  let TopGUIDiv = styled.div`    display: grid;    grid-template-columns: 1fr; @@ -26,6 +27,14 @@ let UserInputQueueItem = styled.div`    text-align: center;  `; +const TopBar = styled.div` +  display: flex; +  flex-direction: row; +  justify-content: space-between; +  padding: 8px; +  align-items: center; +`; +  interface GUIProps {    firstObservation?: any;  } @@ -33,129 +42,128 @@ interface GUIProps {  function GUI(props: GUIProps) {    const [waitingForSteps, setWaitingForSteps] = useState(false);    const [userInputQueue, setUserInputQueue] = useState<string[]>([]); -  const [history, setHistory] = useState<History | undefined>(); -  //   { -  //   timeline: [ -  //     { -  //       step: { -  //         name: "Waiting for user input", -  //         cmd: "python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py", -  //         description: -  //           "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py` and ```\nprint(sum(first, second))\n```\n- Testing\n- Testing 2\n- Testing 3", -  //       }, -  //       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'", -  //       }, -  //       output: [ -  //         { -  //           traceback: { -  //             frames: [ -  //               { -  //                 filepath: -  //                   "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", -  //                 lineno: 7, -  //                 function: "<module>", -  //                 code: "print(sum(first, second))", -  //               }, -  //             ], -  //             message: "unsupported operand type(s) for +: 'int' and 'str'", -  //             error_type: -  //               '          ^^^^^^^^^^^^^^^^^^\n  File "/Users/natesesti/Desktop/continue/extension/examples/python/sum.py", line 2, in sum\n    return a + b\n           ~~^~~\nTypeError', -  //             full_traceback: -  //               "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'", -  //           }, -  //         }, -  //         null, -  //       ], -  //     }, -  //     { -  //       step: { -  //         name: "EditCodeStep", -  //         range_in_files: [ -  //           { -  //             filepath: -  //               "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", -  //             range: { -  //               start: { -  //                 line: 0, -  //                 character: 0, -  //               }, -  //               end: { -  //                 line: 6, -  //                 character: 25, -  //               }, -  //             }, -  //           }, -  //         ], -  //         prompt: -  //           "I ran into this problem with my Python code:\n\n                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'\n\n                Below are the files that might need to be fixed:\n\n                {code}\n\n                This is what the code should be in order to avoid the problem:\n", -  //         description: -  //           "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py` and\n```python\nprint(sum(first, second))\n```\n- Testing\n- Testing 2\n- Testing 3", -  //       }, -  //       output: [ -  //         null, -  //         { -  //           reversible: true, -  //           actions: [ -  //             { -  //               reversible: true, -  //               filesystem: {}, -  //               filepath: -  //                 "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", -  //               range: { -  //                 start: { -  //                   line: 0, -  //                   character: 0, -  //                 }, -  //                 end: { -  //                   line: 6, -  //                   character: 25, -  //                 }, -  //               }, -  //               replacement: -  //                 "\nfrom sum import sum\n\nfirst = 1\nsecond = 2\n\nprint(sum(first, second))", -  //             }, -  //           ], -  //         }, -  //       ], -  //     }, -  //     { -  //       step: { -  //         name: "SolveTracebackStep", -  //         traceback: { -  //           frames: [ -  //             { -  //               filepath: -  //                 "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", -  //               lineno: 7, -  //               function: "<module>", -  //               code: "print(sum(first, second))", -  //             }, -  //           ], -  //           message: "unsupported operand type(s) for +: 'int' and 'str'", -  //           error_type: -  //             '          ^^^^^^^^^^^^^^^^^^\n  File "/Users/natesesti/Desktop/continue/extension/examples/python/sum.py", line 2, in sum\n    return a + b\n           ~~^~~\nTypeError', -  //           full_traceback: -  //             "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'", -  //         }, -  //         description: "Running step: SolveTracebackStep", -  //       }, -  //       output: [null, null], -  //     }, -  //     { -  //       step: { -  //         name: "RunCodeStep", -  //         cmd: "python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py", -  //         description: -  //           "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py`", -  //       }, -  //       output: [null, null], -  //     }, -  //   ], -  //   current_index: 3, -  // } as any); +  const [history, setHistory] = useState<History | undefined>({ +    timeline: [ +      { +        step: { +          name: "Waiting for user input", +          cmd: "python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py", +          description: +            "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py` and ```\nprint(sum(first, second))\n```\n- Testing\n- Testing 2\n- Testing 3", +        }, +        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'", +        }, +        output: [ +          { +            traceback: { +              frames: [ +                { +                  filepath: +                    "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", +                  lineno: 7, +                  function: "<module>", +                  code: "print(sum(first, second))", +                }, +              ], +              message: "unsupported operand type(s) for +: 'int' and 'str'", +              error_type: +                '          ^^^^^^^^^^^^^^^^^^\n  File "/Users/natesesti/Desktop/continue/extension/examples/python/sum.py", line 2, in sum\n    return a + b\n           ~~^~~\nTypeError', +              full_traceback: +                "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'", +            }, +          }, +          null, +        ], +      }, +      { +        step: { +          name: "EditCodeStep", +          range_in_files: [ +            { +              filepath: +                "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", +              range: { +                start: { +                  line: 0, +                  character: 0, +                }, +                end: { +                  line: 6, +                  character: 25, +                }, +              }, +            }, +          ], +          prompt: +            "I ran into this problem with my Python code:\n\n                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'\n\n                Below are the files that might need to be fixed:\n\n                {code}\n\n                This is what the code should be in order to avoid the problem:\n", +          description: +            "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py` and\n```python\nprint(sum(first, second))\n```\n- Testing\n- Testing 2\n- Testing 3", +        }, +        output: [ +          null, +          { +            reversible: true, +            actions: [ +              { +                reversible: true, +                filesystem: {}, +                filepath: +                  "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", +                range: { +                  start: { +                    line: 0, +                    character: 0, +                  }, +                  end: { +                    line: 6, +                    character: 25, +                  }, +                }, +                replacement: +                  "\nfrom sum import sum\n\nfirst = 1\nsecond = 2\n\nprint(sum(first, second))", +              }, +            ], +          }, +        ], +      }, +      { +        step: { +          name: "SolveTracebackStep", +          traceback: { +            frames: [ +              { +                filepath: +                  "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", +                lineno: 7, +                function: "<module>", +                code: "print(sum(first, second))", +              }, +            ], +            message: "unsupported operand type(s) for +: 'int' and 'str'", +            error_type: +              '          ^^^^^^^^^^^^^^^^^^\n  File "/Users/natesesti/Desktop/continue/extension/examples/python/sum.py", line 2, in sum\n    return a + b\n           ~~^~~\nTypeError', +            full_traceback: +              "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'", +          }, +          description: "Running step: SolveTracebackStep", +        }, +        output: [null, null], +      }, +      { +        step: { +          name: "RunCodeStep", +          cmd: "python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py", +          description: +            "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py`", +        }, +        output: [null, null], +      }, +    ], +    current_index: 3, +  } as any);    const topGuiDivRef = useRef<HTMLDivElement>(null);    const client = useContinueGUIProtocol(); @@ -261,6 +269,19 @@ function GUI(props: GUIProps) {          }        }}      > +      <TopBar> +        <h3>Continue</h3> +        <HeaderButton style={{ padding: "3px" }}> +          Clear History +          <Trash +            size="1.6em" +            onClick={() => { +              client?.sendClear(); +            }} +          /> +        </HeaderButton> +      </TopBar> +        {typeof client === "undefined" && (          <>            <Loader></Loader> @@ -288,6 +309,9 @@ function GUI(props: GUIProps) {                client?.retryAtIndex(index);                setWaitingForSteps(true);              }} +            onDelete={() => { +              client?.deleteAtIndex(index); +            }}            />          );        })}  | 
