From ea8e812a9361a609c1d666bd518112196c6e64b0 Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Sun, 18 Jun 2023 18:55:14 -0700
Subject: posthog on data switch, fixed copy button

---
 extension/react-app/src/components/ComboBox.tsx | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'extension/react-app/src/components/ComboBox.tsx')

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.
-- 
cgit v1.2.3-70-g09d2


From 315de821c109a2ac45f4cb553890f941d33104bd Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
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/ComboBox.tsx')

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("<file_prefix>", "").replace("<file_suffix>", "").replace(
-                "<commit_before>", "").replace("<commit_msg>", "").replace("<commit_after>", "")
-            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("<file_prefix>", "").replace("<file_suffix>", "").replace(
+            #     "<commit_before>", "").replace("<commit_msg>", "").replace("<commit_after>", "")
+            # 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 && <Loader></Loader>}
+        {/* {waitingForSteps && <Loader></Loader>} */}
 
         <div>
           {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 3c0d07017e305ca4feca2b884f0e5cee8b04eed3 Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
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/ComboBox.tsx')

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

