From a39bec0dea93c83b5eef446543f991218ecc810c Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Sun, 18 Jun 2023 18:29:20 -0700 Subject: data sharing toggle --- extension/react-app/src/components/HeaderButtonWithText.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'extension/react-app/src/components') diff --git a/extension/react-app/src/components/HeaderButtonWithText.tsx b/extension/react-app/src/components/HeaderButtonWithText.tsx index f9483f0f..acaca9ce 100644 --- a/extension/react-app/src/components/HeaderButtonWithText.tsx +++ b/extension/react-app/src/components/HeaderButtonWithText.tsx @@ -12,7 +12,7 @@ const HeaderButtonWithText = (props: HeaderButtonWithTextProps) => { const [hover, setHover] = useState(false); return ( setHover(true)} onMouseLeave={() => { setHover(false); -- cgit v1.2.3-70-g09d2 From 8aa8e0b5c8402014b01f6ea6ce2e3d686f3c64b2 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Sun, 18 Jun 2023 18:55:14 -0700 Subject: posthog on data switch, fixed copy button --- extension/react-app/src/components/CodeBlock.tsx | 7 +++++-- extension/react-app/src/components/ComboBox.tsx | 9 +++++++++ extension/react-app/src/tabs/gui.tsx | 12 ++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) (limited to 'extension/react-app/src/components') diff --git a/extension/react-app/src/components/CodeBlock.tsx b/extension/react-app/src/components/CodeBlock.tsx index c4524a51..0aae0bbb 100644 --- a/extension/react-app/src/components/CodeBlock.tsx +++ b/extension/react-app/src/components/CodeBlock.tsx @@ -22,7 +22,7 @@ const StyledCopyButton = styled.button<{ visible: boolean }>` /* position: relative; */ float: right; border: none; - background-color: transparent; + background-color: ${secondaryDark}; cursor: pointer; padding: 0; /* margin: 4px; */ @@ -77,7 +77,10 @@ function CodeBlock(props: { language?: string; children: string }) { setHovered(false); }} > - + {props.children} ); diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index ddc9d5dc..8c1f80e0 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -116,6 +116,15 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { disabled={props.disabled} placeholder="Type '/' to see available slash commands." {...getInputProps({ + onChange: (e) => { + const target = e.target as HTMLTextAreaElement; + // Update the height of the textarea to match the content, up to a max of 200px. + target.style.height = "auto"; + target.style.height = `${Math.min( + target.scrollHeight, + 200 + ).toString()}px`; + }, onKeyDown: (event) => { if (event.key === "Enter" && event.shiftKey) { // Prevent Downshift's default 'Enter' behavior. diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 52318dca..eee2b1a0 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -15,6 +15,9 @@ import ComboBox from "../components/ComboBox"; import TextDialog from "../components/TextDialog"; import HeaderButtonWithText from "../components/HeaderButtonWithText"; import ReactSwitch from "react-switch"; +import { usePostHog } from "posthog-js/react"; +import { useSelector } from "react-redux"; +import { RootStore } from "../redux/store"; const TopGUIDiv = styled.div` overflow: hidden; @@ -46,6 +49,11 @@ interface GUIProps { } function GUI(props: GUIProps) { + const posthog = usePostHog(); + const vscMachineId = useSelector( + (state: RootStore) => state.config.vscMachineId + ); + const [waitingForSteps, setWaitingForSteps] = useState(false); const [userInputQueue, setUserInputQueue] = useState([]); const [availableSlashCommands, setAvailableSlashCommands] = useState< @@ -432,6 +440,10 @@ function GUI(props: GUIProps) { handleDiameter={20} width={40} onChange={() => { + posthog?.capture("data_switch_toggled", { + vscMachineId: vscMachineId, + dataSwitchChecked: !dataSwitchChecked, + }); setDataSwitchChecked((prev) => !prev); }} onColor="#12887a" -- cgit v1.2.3-70-g09d2 From d3756d6477655884de8144784db0d9c4ad20c3fd Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Sun, 18 Jun 2023 21:29:36 -0700 Subject: moving gradient loader --- continuedev/src/continuedev/core/autopilot.py | 2 + continuedev/src/continuedev/core/main.py | 1 + .../react-app/src/components/StepContainer.tsx | 39 +++- extension/react-app/src/tabs/gui.tsx | 255 +++++++++++---------- 4 files changed, 163 insertions(+), 134 deletions(-) (limited to 'extension/react-app/src/components') diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index ee249c0b..8b0eaca3 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -181,6 +181,7 @@ class Autopilot(ContinueBaseModel): # i is now the index of the step that we want to show/rerun self.history.timeline[i].observation = observation + self.history.timeline[i].active = False await self.update_subscribers() @@ -205,6 +206,7 @@ class Autopilot(ContinueBaseModel): # Add observation to history, unless already attached error observation if not caught_error: self.history.timeline[index_of_history_node].observation = observation + self.history.timeline[index_of_history_node].active = False await self.update_subscribers() # Update its description diff --git a/continuedev/src/continuedev/core/main.py b/continuedev/src/continuedev/core/main.py index 0c7ec67f..efb91488 100644 --- a/continuedev/src/continuedev/core/main.py +++ b/continuedev/src/continuedev/core/main.py @@ -21,6 +21,7 @@ class HistoryNode(ContinueBaseModel): observation: Union[Observation, None] depth: int deleted: bool = False + active: bool = True def to_chat_messages(self) -> List[ChatMessage]: if self.step.description is None: diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index 1eb1d1fd..74a1c4e8 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -49,9 +49,13 @@ const StepContainerDiv = styled.div<{ open: boolean }>` /* padding: 8px; */ `; -const HeaderDiv = styled.div<{ error: boolean }>` +const HeaderDiv = styled.div<{ error: boolean; loading: boolean }>` background-color: ${(props) => - props.error ? "#522" : vscBackgroundTransparent}; + props.error + ? "#522" + : props.loading + ? vscBackgroundTransparent + : vscBackground}; display: grid; grid-template-columns: 1fr auto auto; grid-gap: 8px; @@ -76,12 +80,22 @@ const StyledCode = styled.code` color: lightgray; `; +const gradient = keyframes` + 0% { + background-position: 0px 0; + } + 100% { + background-position: 100em 0; + } +`; + const GradientBorder = styled.div<{ borderWidth?: number; borderRadius?: string; borderColor?: string; isFirst: boolean; isLast: boolean; + loading: boolean; }>` border-radius: ${(props) => props.borderRadius || "0"}; padding-top: ${(props) => @@ -91,13 +105,18 @@ const GradientBorder = styled.div<{ background: ${(props) => props.borderColor ? props.borderColor - : `linear-gradient( + : `repeating-linear-gradient( 101.79deg, #12887a 0%, - #87245c 37.64%, - #e12637 65.98%, - #ffb215 110.45% + #87245c 16%, + #e12637 33%, + #ffb215 55%, + #e12637 67%, + #87245c 85%, + #12887a 99% )`}; + animation: ${(props) => (props.loading ? gradient : "")} 6s linear infinite; + background-size: 200% 200%; `; function StepContainer(props: StepContainerProps) { @@ -138,10 +157,15 @@ function StepContainer(props: StepContainerProps) { > { @@ -153,6 +177,7 @@ function StepContainer(props: StepContainerProps) { }} >

diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index eee2b1a0..2b72a63a 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -62,129 +62,129 @@ function GUI(props: GUIProps) { const [dataSwitchChecked, setDataSwitchChecked] = useState(false); const [showDataSharingInfo, setShowDataSharingInfo] = useState(false); const [stepsOpen, setStepsOpen] = useState([]); - const [history, setHistory] = useState(); - // { - // 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 \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: "", - // 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 \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 \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: "", - // 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 \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({ + 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 \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: "", + 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 \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 \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))", + }, + ], + }, + ], + }, + { + active: false, + step: { + name: "SolveTracebackStep", + traceback: { + frames: [ + { + filepath: + "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", + lineno: 7, + function: "", + 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 \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 [showFeedbackDialog, setShowFeedbackDialog] = useState(false); @@ -270,8 +270,9 @@ function GUI(props: GUIProps) { const onMainTextInput = () => { if (mainTextInputRef.current) { - if (!client) return; let input = mainTextInputRef.current.value; + mainTextInputRef.current.value = ""; + if (!client) return; if ( history?.timeline.length && @@ -449,7 +450,7 @@ function GUI(props: GUIProps) { onColor="#12887a" checked={dataSwitchChecked} /> - + Contribute Data @@ -457,12 +458,12 @@ function GUI(props: GUIProps) { onClick={() => { client?.sendClear(); }} - text="Clear History" + text="Clear All" > - + -- cgit v1.2.3-70-g09d2 From 31764f5940f34157345f77f7d04265afa603bb5a Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Mon, 19 Jun 2023 09:59:01 -0700 Subject: check for codespaces, stream edits --- continuedev/poetry.lock | 14 ++- continuedev/pyproject.toml | 1 + continuedev/src/continuedev/libs/util/telemetry.py | 16 ++- continuedev/src/continuedev/steps/core/core.py | 109 +++++++++++++++------ extension/react-app/src/components/ComboBox.tsx | 2 +- extension/react-app/src/tabs/gui.tsx | 4 +- extension/src/continueIdeClient.ts | 7 +- 7 files changed, 111 insertions(+), 42 deletions(-) (limited to 'extension/react-app/src/components') diff --git a/continuedev/poetry.lock b/continuedev/poetry.lock index 93aaf82b..017f12f9 100644 --- a/continuedev/poetry.lock +++ b/continuedev/poetry.lock @@ -585,6 +585,18 @@ files = [ {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] +[[package]] +name = "jsonref" +version = "1.1.0" +description = "jsonref is a library for automatic dereferencing of JSON Reference objects for Python." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jsonref-1.1.0-py3-none-any.whl", hash = "sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9"}, + {file = "jsonref-1.1.0.tar.gz", hash = "sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552"}, +] + [[package]] name = "langchain" version = "0.0.171" @@ -1737,4 +1749,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "17910714e3ad780ae7222b62c98539489d198aea67e5c7e4a9fc7672207f500f" +content-hash = "9406bc70d0463b354c294bd9548897a33270b8a04f55141a763d45af8d6928b8" diff --git a/continuedev/pyproject.toml b/continuedev/pyproject.toml index af6ff045..bbd8a687 100644 --- a/continuedev/pyproject.toml +++ b/continuedev/pyproject.toml @@ -21,6 +21,7 @@ urllib3 = "1.26.15" gpt-index = "^0.6.8" posthog = "^3.0.1" tiktoken = "^0.4.0" +jsonref = "^1.1.0" [tool.poetry.scripts] typegen = "src.continuedev.models.generate_json_schema:main" diff --git a/continuedev/src/continuedev/libs/util/telemetry.py b/continuedev/src/continuedev/libs/util/telemetry.py index 03ec93c6..bd9fde9d 100644 --- a/continuedev/src/continuedev/libs/util/telemetry.py +++ b/continuedev/src/continuedev/libs/util/telemetry.py @@ -1,12 +1,22 @@ +from typing import Any from posthog import Posthog from ...core.config import load_config +import os +from dotenv import load_dotenv + +load_dotenv() +in_codespaces = os.getenv("CODESPACES") == "true" # The personal API key is necessary only if you want to use local evaluation of feature flags. posthog = Posthog('phc_JS6XFROuNbhJtVCEdTSYk6gl5ArRrTNMpCcguAXlSPs', host='https://app.posthog.com') -def capture_event(unique_id: str, event_name, event_properties): +def capture_event(unique_id: str, event_name: str, event_properties: Any): config = load_config('.continue/config.json') - if config.allow_anonymous_telemetry: - posthog.capture(unique_id, event_name, event_properties) + if not config.allow_anonymous_telemetry: + return + + if in_codespaces: + event_properties['codespaces'] = True + posthog.capture(unique_id, event_name, event_properties) diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 6d6246fd..237171a6 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -235,45 +235,90 @@ class DefaultModelEditCodeStep(Step): prompt = self._prompt.format( code=rif.contents, user_request=self.user_input, file_prefix=segs[0], file_suffix=segs[1]) - completion = str(await model_to_use.complete(prompt, with_history=await sdk.get_chat_context())) - - eot_token = "<|endoftext|>" - completion = completion.removesuffix(eot_token) - - # Remove tags and If it accidentally includes prefix or suffix, remove it - if completion.strip().startswith("```"): - completion = completion.strip().removeprefix("```").removesuffix("```") - completion = completion.replace("", "").replace("", "").replace( - "", "").replace("", "").replace("", "") - completion = completion.removeprefix(segs[0]) - completion = completion.removesuffix(segs[1]) + lines = [] + unfinished_line = "" + i = 0 + original_lines = rif.contents.split("\n") + lines_to_highlight = [] + + async def add_line(i: int, line: str): + range = Range.from_shorthand( + rif.range.start.line + i, rif.range.start.character if i == 0 else 0, rif.range.start.line + i + 1, 0) + await sdk.ide.applyFileSystemEdit(FileEdit( + filepath=rif.filepath, + range=range, + replacement=line + "\n" + )) + lines_to_highlight.append(rif.range.start.line + i) + # await sdk.ide.highlightCode(RangeInFile( + # filepath=rif.filepath, + # range=range + # )) + + async for chunk in model_to_use.stream_chat(prompt, with_history=await sdk.get_chat_context()): + chunk_lines = chunk.split("\n") + chunk_lines[0] = unfinished_line + chunk_lines[0] + if chunk.endswith("\n"): + unfinished_line = "" + chunk_lines.pop() # because this will be an empty string + else: + unfinished_line = chunk_lines.pop() + lines.extend(chunk_lines) + + for line in chunk_lines: + if i < len(original_lines) and line == original_lines[i]: + i += 1 + continue + + await add_line(i, line) + i += 1 + + # Add the unfinished line + if unfinished_line != "": + if not i < len(original_lines) or not unfinished_line == original_lines[i]: + await add_line(i, unfinished_line) + lines.append(unfinished_line) + i += 1 + + # Remove the leftover original lines + while i < len(original_lines): + range = Range.from_shorthand( + rif.range.start.line + i, rif.range.start.character, rif.range.start.line + i, len(original_lines[i])) + await sdk.ide.applyFileSystemEdit(FileEdit( + filepath=rif.filepath, + range=range, + replacement="" + )) + # await sdk.ide.highlightCode(RangeInFile( + # filepath=rif.filepath, + # range=range + # )) + i += 1 + + completion = "\n".join(lines) + # eot_token = "<|endoftext|>" + # completion = completion.removesuffix(eot_token) + + # # Remove tags and If it accidentally includes prefix or suffix, remove it + # if completion.strip().startswith("```"): + # completion = completion.strip().removeprefix("```").removesuffix("```") + # completion = completion.replace("", "").replace("", "").replace( + # "", "").replace("", "").replace("", "") + # completion = completion.removeprefix(segs[0]) + # completion = completion.removesuffix(segs[1]) self._prompt_and_completion += prompt + completion - diff = list(difflib.ndiff(rif.contents.splitlines( - keepends=True), completion.splitlines(keepends=True))) - - lines_to_highlight = set() - index = 0 - for line in diff: - if line.startswith("-"): - pass - elif line.startswith("+"): - lines_to_highlight.add(index + rif.range.start.line) - index += 1 - elif line.startswith(" "): - index += 1 - - await sdk.ide.applyFileSystemEdit(FileEdit( - filepath=rif.filepath, - range=rif.range, - replacement=completion - )) + # await sdk.ide.applyFileSystemEdit(FileEdit( + # filepath=rif.filepath, + # range=rif.range, + # replacement=completion + # )) current_hl_start = None last_hl = None rifs_to_highlight = [] - for line in sorted(list(lines_to_highlight)): + for line in lines_to_highlight: if current_hl_start is None: current_hl_start = line elif line != last_hl + 1: diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index 8c1f80e0..1a3a2b90 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -122,7 +122,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { target.style.height = "auto"; target.style.height = `${Math.min( target.scrollHeight, - 200 + 300 ).toString()}px`; }, onKeyDown: (event) => { diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 7716d561..62d44515 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -364,7 +364,7 @@ function GUI(props: GUIProps) { setStepsOpen(nextStepsOpen); }} onToggleAll={() => { - setStepsOpen((prev) => prev.map(() => !prev[index])); + setStepsOpen((prev) => prev.map((_, index) => !prev[index])); }} key={index} onUserInput={(input: string) => { @@ -388,7 +388,7 @@ function GUI(props: GUIProps) { /> ); })} - {waitingForSteps && } + {/* {waitingForSteps && } */}
{userInputQueue.map((input) => { diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index 3b5de93f..fbad5f5d 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -159,7 +159,7 @@ class IdeProtocolClient { editor.setDecorations(decorationType, [range]); // Listen for changes to cursor position and then remove the decoration (but keep for at least 2 seconds) - setTimeout(() => { + const allowRemoveHighlight = () => { const cursorDisposable = vscode.window.onDidChangeTextEditorSelection( (event) => { if (event.textEditor.document.uri.fsPath === rangeInFile.filepath) { @@ -168,7 +168,8 @@ class IdeProtocolClient { } } ); - }, 2000); + }; + setTimeout(allowRemoveHighlight, 2000); } } @@ -285,7 +286,7 @@ class IdeProtocolClient { edit.range.start.line, edit.range.start.character, edit.range.end.line, - edit.range.end.character + 1 + edit.range.end.character ); editor.edit((editBuilder) => { -- cgit v1.2.3-70-g09d2 From 1e1feb20e1cc5cf76e7ee078177e8a4ff8bd043d Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Mon, 19 Jun 2023 10:09:41 -0700 Subject: fix up/down arrow key behavior in main entry --- extension/react-app/src/components/ComboBox.tsx | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'extension/react-app/src/components') diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index 1a3a2b90..3816cee8 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -145,14 +145,24 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { } else if (event.key === "Tab" && items.length > 0) { setInputValue(items[0].name); event.preventDefault(); - } else if (event.key === "ArrowUp") { + } else if ( + event.key === "ArrowUp" || + (event.key === "ArrowDown" && + event.currentTarget.value.split("\n").length > 1) + ) { + (event.nativeEvent as any).preventDownshiftDefault = true; + } else if ( + event.key === "ArrowUp" && + event.currentTarget.value.split("\n").length > 1 + ) { if (positionInHistory == 0) return; setInputValue(history[positionInHistory - 1]); setPositionInHistory((prev) => prev - 1); - } else if (event.key === "ArrowDown") { - if (positionInHistory >= history.length - 1) { - setInputValue(""); - } else { + } else if ( + event.key === "ArrowDown" && + event.currentTarget.value.split("\n").length > 1 + ) { + if (positionInHistory < history.length - 1) { setInputValue(history[positionInHistory + 1]); } setPositionInHistory((prev) => -- cgit v1.2.3-70-g09d2 From cfee19c8faad0eb5216e49f174e27aeb388e7830 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Thu, 22 Jun 2023 17:02:50 -0700 Subject: added continue retro button icon --- extension/react-app/src/components/ContinueButton.tsx | 13 +++++++++++-- extension/react-app/src/components/DebugPanel.tsx | 2 ++ extension/react-app/src/redux/slices/configSlice.ts | 16 ++++++++++++++-- extension/react-app/src/redux/store.ts | 1 + extension/src/debugPanel.ts | 4 ++++ 5 files changed, 32 insertions(+), 4 deletions(-) (limited to 'extension/react-app/src/components') diff --git a/extension/react-app/src/components/ContinueButton.tsx b/extension/react-app/src/components/ContinueButton.tsx index c6117bf9..ef6719b7 100644 --- a/extension/react-app/src/components/ContinueButton.tsx +++ b/extension/react-app/src/components/ContinueButton.tsx @@ -1,6 +1,8 @@ import styled, { keyframes } from "styled-components"; import { Button } from "."; import { Play } from "@styled-icons/heroicons-outline"; +import { useSelector } from "react-redux"; +import { RootStore } from "../redux/store"; let StyledButton = styled(Button)` margin: auto; @@ -25,14 +27,21 @@ let StyledButton = styled(Button)` `; function ContinueButton(props: { onClick?: () => void; hidden?: boolean }) { + const vscMediaUrl = useSelector( + (state: RootStore) => state.config.vscMediaUrl + ); + return ( ); diff --git a/extension/react-app/src/components/DebugPanel.tsx b/extension/react-app/src/components/DebugPanel.tsx index 30f38779..94dbac9e 100644 --- a/extension/react-app/src/components/DebugPanel.tsx +++ b/extension/react-app/src/components/DebugPanel.tsx @@ -6,6 +6,7 @@ import { setApiUrl, setVscMachineId, setSessionId, + setVscMediaUrl, } from "../redux/slices/configSlice"; import { setHighlightedCode } from "../redux/slices/miscSlice"; import { updateFileSystem } from "../redux/slices/debugContexSlice"; @@ -37,6 +38,7 @@ function DebugPanel(props: DebugPanelProps) { dispatch(setApiUrl(event.data.apiUrl)); dispatch(setVscMachineId(event.data.vscMachineId)); dispatch(setSessionId(event.data.sessionId)); + dispatch(setVscMediaUrl(event.data.vscMediaUrl)); break; case "highlightedCode": dispatch(setHighlightedCode(event.data.rangeInFile)); diff --git a/extension/react-app/src/redux/slices/configSlice.ts b/extension/react-app/src/redux/slices/configSlice.ts index a6a641e6..1b107bed 100644 --- a/extension/react-app/src/redux/slices/configSlice.ts +++ b/extension/react-app/src/redux/slices/configSlice.ts @@ -37,9 +37,21 @@ export const configSlice = createSlice({ ...state, sessionId: action.payload, }), + setVscMediaUrl: ( + state: RootStore["config"], + action: { type: string; payload: string } + ) => ({ + ...state, + vscMediaUrl: action.payload, + }), }, }); -export const { setVscMachineId, setApiUrl, setWorkspacePath, setSessionId } = - configSlice.actions; +export const { + setVscMachineId, + setApiUrl, + setWorkspacePath, + setSessionId, + setVscMediaUrl, +} = configSlice.actions; export default configSlice.reducer; diff --git a/extension/react-app/src/redux/store.ts b/extension/react-app/src/redux/store.ts index f9eb0517..a5eef4ba 100644 --- a/extension/react-app/src/redux/store.ts +++ b/extension/react-app/src/redux/store.ts @@ -21,6 +21,7 @@ export interface RootStore { vscMachineId: string | undefined; sessionId: string | undefined; sessionStarted: number | undefined; + vscMediaUrl: string | undefined; }; chat: { messages: ChatMessage[]; diff --git a/extension/src/debugPanel.ts b/extension/src/debugPanel.ts index 232203b9..b0db590a 100644 --- a/extension/src/debugPanel.ts +++ b/extension/src/debugPanel.ts @@ -136,6 +136,9 @@ export function setupDebugPanel( let extensionUri = getExtensionUri(); let scriptUri: string; let styleMainUri: string; + let vscMediaUrl: string = debugPanelWebview + .asWebviewUri(vscode.Uri.joinPath(extensionUri, "react-app/dist")) + .toString(); const isProduction = true; // context?.extensionMode === vscode.ExtensionMode.Development; if (!isProduction) { @@ -226,6 +229,7 @@ export function setupDebugPanel( vscMachineId: vscode.env.machineId, apiUrl: getContinueServerUrl(), sessionId, + vscMediaUrl, }); // // Listen for changes to server URL in settings -- cgit v1.2.3-70-g09d2 From 4b394e96a57e0a018cb815e929bf28b445e17ae0 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Sun, 25 Jun 2023 13:44:31 -0700 Subject: don't call python function, other --- continuedev/src/continuedev/libs/llm/openai.py | 2 +- continuedev/src/continuedev/steps/chat.py | 13 +++++++++++-- continuedev/src/continuedev/steps/core/core.py | 3 ++- continuedev/src/continuedev/steps/main.py | 5 +++-- extension/react-app/src/components/HeaderButtonWithText.tsx | 2 ++ extension/react-app/src/components/StepContainer.tsx | 1 + 6 files changed, 20 insertions(+), 6 deletions(-) (limited to 'extension/react-app/src/components') diff --git a/continuedev/src/continuedev/libs/llm/openai.py b/continuedev/src/continuedev/libs/llm/openai.py index aa12d70a..7621111f 100644 --- a/continuedev/src/continuedev/libs/llm/openai.py +++ b/continuedev/src/continuedev/libs/llm/openai.py @@ -70,7 +70,7 @@ class OpenAI(LLM): messages=compile_chat_messages( args["model"], with_history, prompt, with_functions=False), **args, - )).choices[0].message + )).choices[0].message.content else: resp = (await openai.Completion.acreate( prompt=prompt, diff --git a/continuedev/src/continuedev/steps/chat.py b/continuedev/src/continuedev/steps/chat.py index 76fead9d..a940c3ba 100644 --- a/continuedev/src/continuedev/steps/chat.py +++ b/continuedev/src/continuedev/steps/chat.py @@ -105,7 +105,7 @@ class ViewDirectoryTreeStep(Step): class EditFileStep(Step): name: str = "Edit File" - description: str = "Edit a file in the workspace." + description: str = "Edit a file in the workspace that is not currently open." filename: str instructions: str hide: bool = True @@ -136,7 +136,7 @@ class ChatWithFunctions(Step): self.chat_context.append(ChatMessage( role="user", - content=self.user_input, + content=self.user_input + "\n**DO NOT EVER call the 'python' function.**", summary=self.user_input )) @@ -182,6 +182,15 @@ class ChatWithFunctions(Step): else: if func_name == "python" and "python" not in step_name_step_class_map: # GPT must be fine-tuned to believe this exists, but it doesn't always + self.chat_context.append(ChatMessage( + role="assistant", + content=None, + function_call=FunctionCall( + name=func_name, + arguments=func_args + ), + summary=f"Ran function {func_name}" + )) self.chat_context.append(ChatMessage( role="user", content="The 'python' function does not exist. Don't call it.", diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 7ccf82cb..f146c94a 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -213,7 +213,8 @@ class DefaultModelEditCodeStep(Step): if model_to_use.name == "gpt-4": - total_tokens = model_to_use.count_tokens(full_file_contents + self._prompt) + total_tokens = model_to_use.count_tokens( + full_file_contents + self._prompt) cur_start_line, cur_end_line = cut_context( model_to_use, total_tokens, cur_start_line, cur_end_line) diff --git a/continuedev/src/continuedev/steps/main.py b/continuedev/src/continuedev/steps/main.py index bb48dce9..5caac180 100644 --- a/continuedev/src/continuedev/steps/main.py +++ b/continuedev/src/continuedev/steps/main.py @@ -1,7 +1,7 @@ import os from typing import Coroutine, List, Union -from pydantic import BaseModel +from pydantic import BaseModel, Field from ..libs.llm import LLM from ..models.main import Traceback, Range @@ -246,7 +246,8 @@ class StarCoderEditHighlightedCodeStep(Step): class EditHighlightedCodeStep(Step): - user_input: str + user_input: str = Field( + ..., title="User Input", description="The natural language request describing how to edit the code") hide = True description: str = "Change the contents of the currently highlighted code or open file" diff --git a/extension/react-app/src/components/HeaderButtonWithText.tsx b/extension/react-app/src/components/HeaderButtonWithText.tsx index acaca9ce..5901c5d8 100644 --- a/extension/react-app/src/components/HeaderButtonWithText.tsx +++ b/extension/react-app/src/components/HeaderButtonWithText.tsx @@ -6,12 +6,14 @@ interface HeaderButtonWithTextProps { text: string; onClick?: (e: any) => void; children: React.ReactNode; + disabled?: boolean; } const HeaderButtonWithText = (props: HeaderButtonWithTextProps) => { const [hover, setHover] = useState(false); return ( setHover(true)} onMouseLeave={() => { diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index 74a1c4e8..827d2d5f 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -200,6 +200,7 @@ function StepContainer(props: StepContainerProps) { <> { e.stopPropagation(); props.onDelete(); -- cgit v1.2.3-70-g09d2 From 3338d05db9f5f21d8a9d440cb428f2c6a188b363 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Sun, 25 Jun 2023 15:14:56 -0700 Subject: shipped function calling --- continuedev/src/continuedev/core/autopilot.py | 14 ++++++++- continuedev/src/continuedev/steps/chat.py | 33 +++++++++++---------- extension/package-lock.json | 4 +-- extension/package.json | 2 +- .../src/components/HeaderButtonWithText.tsx | 6 +++- extension/react-app/src/tabs/gui.tsx | 2 -- .../scripts/continuedev-0.1.1-py3-none-any.whl | Bin 86716 -> 89177 bytes 7 files changed, 39 insertions(+), 22 deletions(-) (limited to 'extension/react-app/src/components') diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index f14a4127..04f64ed8 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -15,6 +15,17 @@ from .sdk import ContinueSDK import asyncio from ..libs.util.step_name_to_steps import get_step_from_name from ..libs.util.traceback_parsers import get_python_traceback, get_javascript_traceback +from openai import error as openai_errors + + +def get_error_title(e: Exception) -> str: + if isinstance(e, openai_errors.APIError): + return "OpenAI is overloaded with requests. Please try again." + elif isinstance(e, openai_errors.RateLimitError): + return "This OpenAI API key has been rate limited. Please try again." + elif isinstance(e, openai_errors.Timeout): + return "OpenAI timed out. Please try again." + return e.__repr__() class Autopilot(ContinueBaseModel): @@ -166,7 +177,8 @@ class Autopilot(ContinueBaseModel): error_string = e.message if is_continue_custom_exception else '\n\n'.join( traceback.format_tb(e.__traceback__)) + f"\n\n{e.__repr__()}" - error_title = e.title if is_continue_custom_exception else e.__repr__() + error_title = e.title if is_continue_custom_exception else get_error_title( + e) # Attach an InternalErrorObservation to the step and unhide it. print(f"Error while running step: \n{error_string}\n{error_title}") diff --git a/continuedev/src/continuedev/steps/chat.py b/continuedev/src/continuedev/steps/chat.py index a940c3ba..2a8ae2da 100644 --- a/continuedev/src/continuedev/steps/chat.py +++ b/continuedev/src/continuedev/steps/chat.py @@ -182,21 +182,24 @@ class ChatWithFunctions(Step): else: if func_name == "python" and "python" not in step_name_step_class_map: # GPT must be fine-tuned to believe this exists, but it doesn't always - self.chat_context.append(ChatMessage( - role="assistant", - content=None, - function_call=FunctionCall( - name=func_name, - arguments=func_args - ), - summary=f"Ran function {func_name}" - )) - self.chat_context.append(ChatMessage( - role="user", - content="The 'python' function does not exist. Don't call it.", - summary="'python' function does not exist." - )) - continue + func_name = "EditHighlightedCodeStep" + func_args = json.dumps({"user_input": self.user_input}) + # self.chat_context.append(ChatMessage( + # role="assistant", + # content=None, + # function_call=FunctionCall( + # name=func_name, + # arguments=func_args + # ), + # summary=f"Ran function {func_name}" + # )) + # self.chat_context.append(ChatMessage( + # role="user", + # content="The 'python' function does not exist. Don't call it. Try again to call another function.", + # summary="'python' function does not exist." + # )) + # msg_step.hide = True + # continue # Call the function, then continue to chat func_args = "{}" if func_args == "" else func_args fn_call_params = json.loads(func_args) diff --git a/extension/package-lock.json b/extension/package-lock.json index 12b2fe13..71edfe8c 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.0.61", + "version": "0.0.62", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "continue", - "version": "0.0.61", + "version": "0.0.62", "license": "Apache-2.0", "dependencies": { "@electron/rebuild": "^3.2.10", diff --git a/extension/package.json b/extension/package.json index 9fd1d7a6..9679b159 100644 --- a/extension/package.json +++ b/extension/package.json @@ -14,7 +14,7 @@ "displayName": "Continue", "pricing": "Free", "description": "Accelerating software development with language models", - "version": "0.0.61", + "version": "0.0.62", "publisher": "Continue", "engines": { "vscode": "^1.74.0" diff --git a/extension/react-app/src/components/HeaderButtonWithText.tsx b/extension/react-app/src/components/HeaderButtonWithText.tsx index 5901c5d8..30931f86 100644 --- a/extension/react-app/src/components/HeaderButtonWithText.tsx +++ b/extension/react-app/src/components/HeaderButtonWithText.tsx @@ -15,7 +15,11 @@ const HeaderButtonWithText = (props: HeaderButtonWithTextProps) => { setHover(true)} + onMouseEnter={() => { + if (!props.disabled) { + setHover(true); + } + }} onMouseLeave={() => { setHover(false); }} diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 5001fe4b..4886bfad 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -491,8 +491,6 @@ function GUI(props: GUIProps) { { client?.sendClear(); - // Reload the window to get completely fresh session - window.location.reload(); }} text="Clear All" > diff --git a/extension/scripts/continuedev-0.1.1-py3-none-any.whl b/extension/scripts/continuedev-0.1.1-py3-none-any.whl index 29e41d3c..692bdfb7 100644 Binary files a/extension/scripts/continuedev-0.1.1-py3-none-any.whl and b/extension/scripts/continuedev-0.1.1-py3-none-any.whl differ -- cgit v1.2.3-70-g09d2 From 21dc98bb603f6d7cb18a3c3795a18f3070f0254a Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Sun, 25 Jun 2023 21:35:53 -0700 Subject: loading cover page (hidden) --- extension/react-app/public/continue.gif | Bin 0 -> 5242 bytes .../react-app/src/components/LoadingCover.tsx | 50 +++++++++++++++++++++ extension/react-app/src/tabs/gui.tsx | 2 + 3 files changed, 52 insertions(+) create mode 100644 extension/react-app/public/continue.gif create mode 100644 extension/react-app/src/components/LoadingCover.tsx (limited to 'extension/react-app/src/components') diff --git a/extension/react-app/public/continue.gif b/extension/react-app/public/continue.gif new file mode 100644 index 00000000..daed6663 Binary files /dev/null and b/extension/react-app/public/continue.gif differ diff --git a/extension/react-app/src/components/LoadingCover.tsx b/extension/react-app/src/components/LoadingCover.tsx new file mode 100644 index 00000000..a0f8f7a2 --- /dev/null +++ b/extension/react-app/src/components/LoadingCover.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import styled from "styled-components"; + +const StyledDiv = styled.div` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100vh; + background: linear-gradient( + 101.79deg, + #12887a 0%, + #87245c 32%, + #e12637 63%, + #ffb215 100% + ); + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + z-index: 10; +`; + +const StyledImg = styled.img` + /* add your styles here */ +`; + +const StyledDiv2 = styled.div` + width: 50%; + height: 5px; + background: white; + margin-top: 20px; +`; + +interface LoadingCoverProps { + message: string; + hidden?: boolean; +} + +const LoadingCover = (props: LoadingCoverProps) => { + return ( + + + +

{props.message}

+
+ ); +}; + +export default LoadingCover; diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 4886bfad..445d5700 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -18,6 +18,7 @@ import ReactSwitch from "react-switch"; import { usePostHog } from "posthog-js/react"; import { useSelector } from "react-redux"; import { RootStore } from "../redux/store"; +import LoadingCover from "../components/LoadingCover"; const TopGUIDiv = styled.div` overflow: hidden; @@ -328,6 +329,7 @@ function GUI(props: GUIProps) { // const iterations = useSelector(selectIterations); return ( <> +