From 452af6002addd67d7047ce4faa39a680ef2b4439 Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Sat, 1 Jul 2023 14:21:26 -0700
Subject: older @types/vscode version to match older engine

---
 continuedev/src/continuedev/steps/chat.py | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

(limited to 'continuedev/src')

diff --git a/continuedev/src/continuedev/steps/chat.py b/continuedev/src/continuedev/steps/chat.py
index 8494563b..9bb75ab4 100644
--- a/continuedev/src/continuedev/steps/chat.py
+++ b/continuedev/src/continuedev/steps/chat.py
@@ -29,12 +29,20 @@ class SimpleChatStep(Step):
             self.description = ""
         await sdk.update_ui()
 
-        async for chunk in sdk.models.default.stream_complete(self.user_input, with_history=await sdk.get_chat_context()):
+        messages = await sdk.get_chat_context()
+        messages.append(ChatMessage(
+            role="user",
+            content=self.user_input,
+            summary=self.user_input
+        ))
+
+        async for chunk in sdk.models.default.stream_chat(messages):
             if sdk.current_step_was_deleted():
                 return
 
-            self.description += chunk
-            await sdk.update_ui()
+            if "content" in chunk:
+                self.description += chunk["content"]
+                await sdk.update_ui()
 
         self.name = (await sdk.models.gpt35.complete(
             f"Write a short title for the following chat message: {self.description}")).strip()
-- 
cgit v1.2.3-70-g09d2


From a86933aec5243584def582150bbba1a926be9fda Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Sun, 2 Jul 2023 12:47:08 -0700
Subject: ssl certificate fix

---
 continuedev/pyproject.toml                         |  2 +-
 .../src/continuedev/libs/llm/proxy_server.py       | 11 ++++++--
 extension/package-lock.json                        |  4 +--
 extension/package.json                             |  2 +-
 extension/server_version.txt                       |  1 +
 extension/src/activation/environmentSetup.ts       | 32 ++++++++++++----------
 6 files changed, 31 insertions(+), 21 deletions(-)
 create mode 100644 extension/server_version.txt

(limited to 'continuedev/src')

diff --git a/continuedev/pyproject.toml b/continuedev/pyproject.toml
index e33627e7..6727e29a 100644
--- a/continuedev/pyproject.toml
+++ b/continuedev/pyproject.toml
@@ -6,7 +6,7 @@ authors = ["Nate Sesti <sestinj@gmail.com>"]
 readme = "README.md"
 
 [tool.poetry.dependencies]
-python = "^3.9"
+python = "^3.8"
 diff-match-patch = "^20230430"
 fastapi = "^0.95.1"
 typer = "^0.7.0"
diff --git a/continuedev/src/continuedev/libs/llm/proxy_server.py b/continuedev/src/continuedev/libs/llm/proxy_server.py
index bd831ad9..69c96ee8 100644
--- a/continuedev/src/continuedev/libs/llm/proxy_server.py
+++ b/continuedev/src/continuedev/libs/llm/proxy_server.py
@@ -5,6 +5,11 @@ import aiohttp
 from ...core.main import ChatMessage
 from ..llm import LLM
 from ..util.count_tokens import DEFAULT_ARGS, DEFAULT_MAX_TOKENS, compile_chat_messages, CHAT_MODELS, count_tokens
+import certifi
+import ssl
+
+ca_bundle_path = certifi.where()
+ssl_context = ssl.create_default_context(cafile=ca_bundle_path)
 
 # SERVER_URL = "http://127.0.0.1:8080"
 SERVER_URL = "https://proxy-server-l6vsfbzhba-uw.a.run.app"
@@ -31,7 +36,7 @@ class ProxyServer(LLM):
     async def complete(self, prompt: str, with_history: List[ChatMessage] = [], **kwargs) -> Coroutine[Any, Any, str]:
         args = self.default_args | kwargs
 
-        async with aiohttp.ClientSession() as session:
+        async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl_context=ssl_context)) as session:
             async with session.post(f"{SERVER_URL}/complete", json={
                 "messages": compile_chat_messages(args["model"], with_history, prompt, functions=None),
                 "unique_id": self.unique_id,
@@ -47,7 +52,7 @@ class ProxyServer(LLM):
         messages = compile_chat_messages(
             self.default_model, messages, None, functions=args.get("functions", None))
 
-        async with aiohttp.ClientSession() as session:
+        async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl_context=ssl_context)) as session:
             async with session.post(f"{SERVER_URL}/stream_chat", json={
                 "messages": messages,
                 "unique_id": self.unique_id,
@@ -71,7 +76,7 @@ class ProxyServer(LLM):
         messages = compile_chat_messages(
             self.default_model, with_history, prompt, functions=args.get("functions", None))
 
-        async with aiohttp.ClientSession() as session:
+        async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl_context=ssl_context)) as session:
             async with session.post(f"{SERVER_URL}/stream_complete", json={
                 "messages": messages,
                 "unique_id": self.unique_id,
diff --git a/extension/package-lock.json b/extension/package-lock.json
index d988c6a9..7e0c9cde 100644
--- a/extension/package-lock.json
+++ b/extension/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "continue",
-  "version": "0.0.99",
+  "version": "0.0.102",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "continue",
-      "version": "0.0.99",
+      "version": "0.0.102",
       "license": "Apache-2.0",
       "dependencies": {
         "@electron/rebuild": "^3.2.10",
diff --git a/extension/package.json b/extension/package.json
index 5406bb71..9d369724 100644
--- a/extension/package.json
+++ b/extension/package.json
@@ -14,7 +14,7 @@
   "displayName": "Continue",
   "pricing": "Free",
   "description": "The open-source coding autopilot",
-  "version": "0.0.99",
+  "version": "0.0.102",
   "publisher": "Continue",
   "engines": {
     "vscode": "^1.60.0"
diff --git a/extension/server_version.txt b/extension/server_version.txt
new file mode 100644
index 00000000..da5ce208
--- /dev/null
+++ b/extension/server_version.txt
@@ -0,0 +1 @@
+0.0.101
\ No newline at end of file
diff --git a/extension/src/activation/environmentSetup.ts b/extension/src/activation/environmentSetup.ts
index d4c81d2e..7e550ea8 100644
--- a/extension/src/activation/environmentSetup.ts
+++ b/extension/src/activation/environmentSetup.ts
@@ -71,9 +71,11 @@ async function getPythonPipCommands() {
     }
   }
 
+  let pipCmd = pythonCmd.endsWith("3") ? "pip3" : "pip";
+
   const version = stdout.split(" ")[1];
   const [major, minor] = version.split(".");
-  if (parseInt(major) !== 3 || parseInt(minor) < 7) {
+  if (parseInt(major) !== 3 || parseInt(minor) < 8) {
     // Need to check specific versions
     const checkPython3VersionExists = async (minorVersion: number) => {
       const [stdout, stderr] = await runCommand(
@@ -82,24 +84,27 @@ async function getPythonPipCommands() {
       return typeof stderr === "undefined" || stderr === "";
     };
 
-    const validVersions = [7, 8, 9, 10, 11, 12];
+    const VALID_VERSIONS = [8, 9, 10, 11, 12];
     let versionExists = false;
 
-    for (const minorVersion of validVersions) {
+    for (const minorVersion of VALID_VERSIONS) {
       if (await checkPython3VersionExists(minorVersion)) {
         versionExists = true;
-        break;
+        pythonCmd = `python3.${minorVersion}`;
+        pipCmd = `pip3.${minorVersion}`;
       }
     }
 
     if (!versionExists) {
       vscode.window.showErrorMessage(
-        "Continue requires Python3 version 3.7 or greater. Please update your Python3 installation, reload VS Code, and try again."
+        "Continue requires Python3 version 3.8 or greater. Please update your Python3 installation, reload VS Code, and try again."
       );
-      throw new Error("Python3 is not installed.");
+      throw new Error("Python3.8 or greater is not installed.");
     }
+  } else {
+    pythonCmd = `python${major}.${minor}`;
+    pipCmd = `pip${major}.${minor}`;
   }
-  const pipCmd = pythonCmd.endsWith("3") ? "pip3" : "pip";
   return [pythonCmd, pipCmd];
 }
 
@@ -298,14 +303,13 @@ export async function startContinuePythonServer() {
   // Do this after above check so we don't have to waste time setting up the env
   await setupPythonEnv();
 
-  let activateCmd = ". env/bin/activate";
-  let pythonCmd = "python3";
-  if (process.platform == "win32") {
-    activateCmd = ".\\env\\Scripts\\activate";
-    pythonCmd = "python";
-  }
+  const [pythonCmd] = await getPythonPipCommands();
+  const activateCmd =
+    process.platform == "win32"
+      ? ".\\env\\Scripts\\activate"
+      : ". env/bin/activate";
 
-  let command = `cd "${path.join(
+  const command = `cd "${path.join(
     getExtensionUri().fsPath,
     "scripts"
   )}" && ${activateCmd} && cd .. && ${pythonCmd} -m scripts.run_continue_server`;
-- 
cgit v1.2.3-70-g09d2


From 321ba3f949f1e9e39f5a73bba9bbca8739e62ecf Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Sun, 2 Jul 2023 13:02:59 -0700
Subject: track when suggestion is accepted or rejected

---
 continuedev/src/continuedev/server/ide.py          |  9 +++++++--
 continuedev/src/continuedev/server/ide_protocol.py |  2 +-
 extension/src/continueIdeClient.ts                 |  4 ++++
 extension/src/suggestions.ts                       | 23 +++++++++-------------
 4 files changed, 21 insertions(+), 17 deletions(-)

(limited to 'continuedev/src')

diff --git a/continuedev/src/continuedev/server/ide.py b/continuedev/src/continuedev/server/ide.py
index e1f19447..1f790991 100644
--- a/continuedev/src/continuedev/server/ide.py
+++ b/continuedev/src/continuedev/server/ide.py
@@ -7,6 +7,7 @@ import uuid
 from fastapi import WebSocket, Body, APIRouter
 from uvicorn.main import Server
 
+from ..libs.util.telemetry import capture_event
 from ..libs.util.queue import AsyncSubscriptionQueue
 from ..models.filesystem import FileSystem, RangeInFile, EditDiff, RealFileSystem
 from ..models.filesystem_edit import AddDirectory, AddFile, DeleteDirectory, DeleteFile, FileSystemEdit, FileEdit, FileEditWithFullContents, RenameDirectory, RenameFile, SequentialFileSystemEdit
@@ -142,6 +143,8 @@ class IdeProtocolServer(AbstractIdeProtocolServer):
         elif message_type == "commandOutput":
             output = data["output"]
             self.onCommandOutput(output)
+        elif message_type == "acceptRejectSuggestion":
+            self.onAcceptRejectSuggestion(data["accepted"])
         elif message_type in ["highlightedCode", "openFiles", "readFile", "editFile", "workspaceDirectory", "getUserSecret", "runCommand", "uniqueId"]:
             self.sub_queue.post(message_type, data)
         else:
@@ -202,8 +205,10 @@ class IdeProtocolServer(AbstractIdeProtocolServer):
     # This is where you might have triggers: plugins can subscribe to certian events
     # like file changes, tracebacks, etc...
 
-    def onAcceptRejectSuggestion(self, suggestionId: str, accepted: bool):
-        pass
+    def onAcceptRejectSuggestion(self, accepted: bool):
+        capture_event(self.unique_id, "accept_reject_suggestion", {
+            "accepted": accepted
+        })
 
     def onFileSystemUpdate(self, update: FileSystemEdit):
         # Access to Autopilot (so SessionManager)
diff --git a/continuedev/src/continuedev/server/ide_protocol.py b/continuedev/src/continuedev/server/ide_protocol.py
index d2dafa9a..7faf5563 100644
--- a/continuedev/src/continuedev/server/ide_protocol.py
+++ b/continuedev/src/continuedev/server/ide_protocol.py
@@ -36,7 +36,7 @@ class AbstractIdeProtocolServer(ABC):
         """Show suggestions to the user and wait for a response"""
 
     @abstractmethod
-    def onAcceptRejectSuggestion(self, suggestionId: str, accepted: bool):
+    def onAcceptRejectSuggestion(self, accepted: bool):
         """Called when the user accepts or rejects a suggestion"""
 
     @abstractmethod
diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts
index 21104abe..b39e6565 100644
--- a/extension/src/continueIdeClient.ts
+++ b/extension/src/continueIdeClient.ts
@@ -375,6 +375,10 @@ class IdeProtocolClient {
   sendCommandOutput(output: string) {
     this.messenger?.send("commandOutput", { output });
   }
+
+  sendAcceptRejectSuggestion(accepted: boolean) {
+    this.messenger?.send("acceptRejectSuggestion", { accepted });
+  }
 }
 
 export default IdeProtocolClient;
diff --git a/extension/src/suggestions.ts b/extension/src/suggestions.ts
index baa49711..6e5a444f 100644
--- a/extension/src/suggestions.ts
+++ b/extension/src/suggestions.ts
@@ -5,7 +5,7 @@ import { translate, readFileAtRange } from "./util/vscode";
 import * as fs from "fs";
 import * as path from "path";
 import { registerAllCodeLensProviders } from "./lang-server/codeLens";
-import { extensionContext } from "./activation/activate";
+import { extensionContext, ideProtocolClient } from "./activation/activate";
 
 export interface SuggestionRanges {
   oldRange: vscode.Range;
@@ -241,19 +241,14 @@ function selectSuggestion(
       suggestions = JSON.parse(rawData);
     }
 
-    if (accept === "new" || (accept === "selected" && suggestion.newSelected)) {
-      suggestions.push({
-        accepted: true,
-        timestamp: Date.now(),
-        suggestion: suggestion.newContent,
-      });
-    } else {
-      suggestions.push({
-        accepted: false,
-        timestamp: Date.now(),
-        suggestion: suggestion.newContent,
-      });
-    }
+    const accepted =
+      accept === "new" || (accept === "selected" && suggestion.newSelected);
+    suggestions.push({
+      accepted,
+      timestamp: Date.now(),
+      suggestion: suggestion.newContent,
+    });
+    ideProtocolClient.sendAcceptRejectSuggestion(accepted);
 
     // Write the updated suggestions back to the file
     fs.writeFileSync(
-- 
cgit v1.2.3-70-g09d2


From 5948aa251bde983fb3e5ee9782ce17879451f4b8 Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Sun, 2 Jul 2023 15:22:34 -0700
Subject: telemetry to capture errors when setup fails

---
 continuedev/src/continuedev/libs/util/dedent.py |   2 +
 extension/package-lock.json                     | 149 +++++++++++++++++++++++-
 extension/package.json                          |   3 +-
 extension/src/activation/environmentSetup.ts    |  67 ++++++-----
 4 files changed, 187 insertions(+), 34 deletions(-)

(limited to 'continuedev/src')

diff --git a/continuedev/src/continuedev/libs/util/dedent.py b/continuedev/src/continuedev/libs/util/dedent.py
index 74edd173..bbbeba5e 100644
--- a/continuedev/src/continuedev/libs/util/dedent.py
+++ b/continuedev/src/continuedev/libs/util/dedent.py
@@ -3,6 +3,8 @@ from typing import Tuple
 
 def dedent_and_get_common_whitespace(s: str) -> Tuple[str, str]:
     lines = s.splitlines()
+    if len(lines) == 0:
+        return "", ""
 
     # Longest common whitespace prefix
     lcp = lines[0].split(lines[0].strip())[0]
diff --git a/extension/package-lock.json b/extension/package-lock.json
index 7e0c9cde..5ebd645c 100644
--- a/extension/package-lock.json
+++ b/extension/package-lock.json
@@ -1,17 +1,18 @@
 {
   "name": "continue",
-  "version": "0.0.102",
+  "version": "0.0.103",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "continue",
-      "version": "0.0.102",
+      "version": "0.0.103",
       "license": "Apache-2.0",
       "dependencies": {
         "@electron/rebuild": "^3.2.10",
         "@reduxjs/toolkit": "^1.9.3",
         "@segment/analytics-node": "^0.0.1-beta.16",
+        "@sentry/node": "^7.57.0",
         "@styled-icons/heroicons-outline": "^10.47.0",
         "@vitejs/plugin-react-swc": "^3.3.2",
         "axios": "^1.2.5",
@@ -1331,6 +1332,71 @@
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
       "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
     },
+    "node_modules/@sentry-internal/tracing": {
+      "version": "7.57.0",
+      "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.57.0.tgz",
+      "integrity": "sha512-tpViyDd8AhQGYYhI94xi2aaDopXOPfL2Apwrtb3qirWkomIQ2K86W1mPmkce+B0cFOnW2Dxv/ZTFKz6ghjK75A==",
+      "dependencies": {
+        "@sentry/core": "7.57.0",
+        "@sentry/types": "7.57.0",
+        "@sentry/utils": "7.57.0",
+        "tslib": "^2.4.1 || ^1.9.3"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@sentry/core": {
+      "version": "7.57.0",
+      "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.57.0.tgz",
+      "integrity": "sha512-l014NudPH0vQlzybtXajPxYFfs9w762NoarjObC3gu76D1jzBBFzhdRelkGpDbSLNTIsKhEDDRpgAjBWJ9icfw==",
+      "dependencies": {
+        "@sentry/types": "7.57.0",
+        "@sentry/utils": "7.57.0",
+        "tslib": "^2.4.1 || ^1.9.3"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@sentry/node": {
+      "version": "7.57.0",
+      "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.57.0.tgz",
+      "integrity": "sha512-63mjyUVM6sfJFVQ5TGVRVGUsoEfESl5ABzIW1W0s9gUiQPaG8SOdaQJglb2VNrkMYxnRHgD8Q9LUh/qcmUyPGw==",
+      "dependencies": {
+        "@sentry-internal/tracing": "7.57.0",
+        "@sentry/core": "7.57.0",
+        "@sentry/types": "7.57.0",
+        "@sentry/utils": "7.57.0",
+        "cookie": "^0.4.1",
+        "https-proxy-agent": "^5.0.0",
+        "lru_map": "^0.3.3",
+        "tslib": "^2.4.1 || ^1.9.3"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@sentry/types": {
+      "version": "7.57.0",
+      "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.57.0.tgz",
+      "integrity": "sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@sentry/utils": {
+      "version": "7.57.0",
+      "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.57.0.tgz",
+      "integrity": "sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg==",
+      "dependencies": {
+        "@sentry/types": "7.57.0",
+        "tslib": "^2.4.1 || ^1.9.3"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/@sindresorhus/is": {
       "version": "4.6.0",
       "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
@@ -2940,6 +3006,14 @@
         "node": "> 0.10"
       }
     },
+    "node_modules/cookie": {
+      "version": "0.4.2",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
+      "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
     "node_modules/core-util-is": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -5183,6 +5257,11 @@
         "node": ">=8"
       }
     },
+    "node_modules/lru_map": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
+      "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ=="
+    },
     "node_modules/lru-cache": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -8183,8 +8262,7 @@
     "node_modules/tslib": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-      "dev": true
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
     },
     "node_modules/tsutils": {
       "version": "3.21.0",
@@ -9808,6 +9886,56 @@
         }
       }
     },
+    "@sentry-internal/tracing": {
+      "version": "7.57.0",
+      "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.57.0.tgz",
+      "integrity": "sha512-tpViyDd8AhQGYYhI94xi2aaDopXOPfL2Apwrtb3qirWkomIQ2K86W1mPmkce+B0cFOnW2Dxv/ZTFKz6ghjK75A==",
+      "requires": {
+        "@sentry/core": "7.57.0",
+        "@sentry/types": "7.57.0",
+        "@sentry/utils": "7.57.0",
+        "tslib": "^2.4.1 || ^1.9.3"
+      }
+    },
+    "@sentry/core": {
+      "version": "7.57.0",
+      "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.57.0.tgz",
+      "integrity": "sha512-l014NudPH0vQlzybtXajPxYFfs9w762NoarjObC3gu76D1jzBBFzhdRelkGpDbSLNTIsKhEDDRpgAjBWJ9icfw==",
+      "requires": {
+        "@sentry/types": "7.57.0",
+        "@sentry/utils": "7.57.0",
+        "tslib": "^2.4.1 || ^1.9.3"
+      }
+    },
+    "@sentry/node": {
+      "version": "7.57.0",
+      "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.57.0.tgz",
+      "integrity": "sha512-63mjyUVM6sfJFVQ5TGVRVGUsoEfESl5ABzIW1W0s9gUiQPaG8SOdaQJglb2VNrkMYxnRHgD8Q9LUh/qcmUyPGw==",
+      "requires": {
+        "@sentry-internal/tracing": "7.57.0",
+        "@sentry/core": "7.57.0",
+        "@sentry/types": "7.57.0",
+        "@sentry/utils": "7.57.0",
+        "cookie": "^0.4.1",
+        "https-proxy-agent": "^5.0.0",
+        "lru_map": "^0.3.3",
+        "tslib": "^2.4.1 || ^1.9.3"
+      }
+    },
+    "@sentry/types": {
+      "version": "7.57.0",
+      "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.57.0.tgz",
+      "integrity": "sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w=="
+    },
+    "@sentry/utils": {
+      "version": "7.57.0",
+      "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.57.0.tgz",
+      "integrity": "sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg==",
+      "requires": {
+        "@sentry/types": "7.57.0",
+        "tslib": "^2.4.1 || ^1.9.3"
+      }
+    },
     "@sindresorhus/is": {
       "version": "4.6.0",
       "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
@@ -10937,6 +11065,11 @@
         "easy-table": "1.1.0"
       }
     },
+    "cookie": {
+      "version": "0.4.2",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
+      "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
+    },
     "core-util-is": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -12603,6 +12736,11 @@
       "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
       "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="
     },
+    "lru_map": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
+      "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ=="
+    },
     "lru-cache": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -14662,8 +14800,7 @@
     "tslib": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-      "dev": true
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
     },
     "tsutils": {
       "version": "3.21.0",
diff --git a/extension/package.json b/extension/package.json
index 9d369724..b77ba064 100644
--- a/extension/package.json
+++ b/extension/package.json
@@ -14,7 +14,7 @@
   "displayName": "Continue",
   "pricing": "Free",
   "description": "The open-source coding autopilot",
-  "version": "0.0.102",
+  "version": "0.0.103",
   "publisher": "Continue",
   "engines": {
     "vscode": "^1.60.0"
@@ -240,6 +240,7 @@
     "@electron/rebuild": "^3.2.10",
     "@reduxjs/toolkit": "^1.9.3",
     "@segment/analytics-node": "^0.0.1-beta.16",
+    "@sentry/node": "^7.57.0",
     "@styled-icons/heroicons-outline": "^10.47.0",
     "@vitejs/plugin-react-swc": "^3.3.2",
     "axios": "^1.2.5",
diff --git a/extension/src/activation/environmentSetup.ts b/extension/src/activation/environmentSetup.ts
index 7e550ea8..4e6be9b3 100644
--- a/extension/src/activation/environmentSetup.ts
+++ b/extension/src/activation/environmentSetup.ts
@@ -9,6 +9,7 @@ import { getContinueServerUrl } from "../bridge";
 import fetch from "node-fetch";
 import * as vscode from "vscode";
 import fkill from "fkill";
+import { sendTelemetryEvent, TelemetryEvent } from "../telemetry";
 
 const MAX_RETRIES = 5;
 async function retryThenFail(
@@ -17,13 +18,16 @@ async function retryThenFail(
 ): Promise<any> {
   try {
     return await fn();
-  } catch (e) {
+  } catch (e: any) {
     if (retries > 0) {
       return await retryThenFail(fn, retries - 1);
     }
     vscode.window.showErrorMessage(
       "Failed to set up Continue extension. Please email nate@continue.dev and we'll get this fixed ASAP!"
     );
+    sendTelemetryEvent(TelemetryEvent.ExtensionSetupError, {
+      error: e.message,
+    });
     throw e;
   }
 }
@@ -47,6 +51,12 @@ async function runCommand(cmd: string): Promise<[string, string | undefined]> {
     stdout = "";
   }
 
+  if (stderr) {
+    sendTelemetryEvent(TelemetryEvent.ExtensionSetupError, {
+      error: stderr,
+    });
+  }
+
   return [stdout, stderr];
 }
 
@@ -288,33 +298,33 @@ export async function startContinuePythonServer() {
     return;
   }
 
-  if (await checkServerRunning(serverUrl)) {
-    // Kill the server if it is running an old version
-    if (fs.existsSync(serverVersionPath())) {
-      const serverVersion = fs.readFileSync(serverVersionPath(), "utf8");
-      if (serverVersion === getExtensionVersion()) {
-        return;
+  return await retryThenFail(async () => {
+    if (await checkServerRunning(serverUrl)) {
+      // Kill the server if it is running an old version
+      if (fs.existsSync(serverVersionPath())) {
+        const serverVersion = fs.readFileSync(serverVersionPath(), "utf8");
+        if (serverVersion === getExtensionVersion()) {
+          return;
+        }
       }
+      console.log("Killing old server...");
+      await fkill(":65432");
     }
-    console.log("Killing old server...");
-    await fkill(":65432");
-  }
 
-  // Do this after above check so we don't have to waste time setting up the env
-  await setupPythonEnv();
+    // Do this after above check so we don't have to waste time setting up the env
+    await setupPythonEnv();
 
-  const [pythonCmd] = await getPythonPipCommands();
-  const activateCmd =
-    process.platform == "win32"
-      ? ".\\env\\Scripts\\activate"
-      : ". env/bin/activate";
+    const [pythonCmd] = await getPythonPipCommands();
+    const activateCmd =
+      process.platform == "win32"
+        ? ".\\env\\Scripts\\activate"
+        : ". env/bin/activate";
 
-  const command = `cd "${path.join(
-    getExtensionUri().fsPath,
-    "scripts"
-  )}" && ${activateCmd} && cd .. && ${pythonCmd} -m scripts.run_continue_server`;
+    const command = `cd "${path.join(
+      getExtensionUri().fsPath,
+      "scripts"
+    )}" && ${activateCmd} && cd .. && ${pythonCmd} -m scripts.run_continue_server`;
 
-  return await retryThenFail(async () => {
     console.log("Starting Continue python server...");
 
     return new Promise(async (resolve, reject) => {
@@ -322,22 +332,25 @@ export async function startContinuePythonServer() {
         const child = spawn(command, {
           shell: true,
         });
-        child.stdout.on("data", (data: any) => {
-          console.log(`stdout: ${data}`);
-        });
         child.stderr.on("data", (data: any) => {
+          console.log(`stdout: ${data}`);
           if (
             data.includes("Uvicorn running on") || // Successfully started the server
             data.includes("address already in use") // The server is already running (probably a simultaneously opened VS Code window)
           ) {
             console.log("Successfully started Continue python server");
             resolve(null);
-          } else {
-            console.log(`stderr: ${data}`);
+          } else if (data.includes("ERROR") || data.includes("Traceback")) {
+            sendTelemetryEvent(TelemetryEvent.ExtensionSetupError, {
+              error: data,
+            });
           }
         });
         child.on("error", (error: any) => {
           console.log(`error: ${error.message}`);
+          sendTelemetryEvent(TelemetryEvent.ExtensionSetupError, {
+            error: error.message,
+          });
         });
 
         // Write the current version of vscode to a file called server_version.txt
-- 
cgit v1.2.3-70-g09d2


From 4657f30167d18c42aa66cdd841965c9661669d3f Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Sun, 2 Jul 2023 15:47:14 -0700
Subject: no more gpt-3.5-turbo

---
 continuedev/src/continuedev/steps/chat.py         |  2 +-
 continuedev/src/continuedev/steps/core/core.py    |  2 +-
 extension/react-app/src/components/TextDialog.tsx |  3 ++-
 extension/react-app/src/tabs/gui.tsx              | 22 +++++++++++++++++-----
 4 files changed, 21 insertions(+), 8 deletions(-)

(limited to 'continuedev/src')

diff --git a/continuedev/src/continuedev/steps/chat.py b/continuedev/src/continuedev/steps/chat.py
index 9bb75ab4..2efef37d 100644
--- a/continuedev/src/continuedev/steps/chat.py
+++ b/continuedev/src/continuedev/steps/chat.py
@@ -36,7 +36,7 @@ class SimpleChatStep(Step):
             summary=self.user_input
         ))
 
-        async for chunk in sdk.models.default.stream_chat(messages):
+        async for chunk in sdk.models.gpt4.stream_chat(messages):
             if sdk.current_step_was_deleted():
                 return
 
diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py
index a84263cc..345d99bc 100644
--- a/continuedev/src/continuedev/steps/core/core.py
+++ b/continuedev/src/continuedev/steps/core/core.py
@@ -172,7 +172,7 @@ class DefaultModelEditCodeStep(Step):
         # We don't know here all of the functions being passed in.
         # We care because if this prompt itself goes over the limit, then the entire message will have to be cut from the completion.
         # Overflow won't happen, but prune_chat_messages in count_tokens.py will cut out this whole thing, instead of us cutting out only as many lines as we need.
-        model_to_use = sdk.models.default
+        model_to_use = sdk.models.gpt4
 
         BUFFER_FOR_FUNCTIONS = 400
         total_tokens = model_to_use.count_tokens(
diff --git a/extension/react-app/src/components/TextDialog.tsx b/extension/react-app/src/components/TextDialog.tsx
index 2632e572..a564f884 100644
--- a/extension/react-app/src/components/TextDialog.tsx
+++ b/extension/react-app/src/components/TextDialog.tsx
@@ -52,6 +52,7 @@ const TextDialog = (props: {
   showDialog: boolean;
   onEnter: (text: string) => void;
   onClose: () => void;
+  message?: string;
 }) => {
   const [text, setText] = useState("");
   const textAreaRef = React.createRef<HTMLTextAreaElement>();
@@ -75,7 +76,7 @@ const TextDialog = (props: {
         }}
       >
         <Dialog>
-          <P>Thanks for your feedback. We'll get back to you soon!</P>
+          <P>{props.message || ""}</P>
           <TextArea
             rows={10}
             ref={textAreaRef}
diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx
index 39925fc5..bc0e5365 100644
--- a/extension/react-app/src/tabs/gui.tsx
+++ b/extension/react-app/src/tabs/gui.tsx
@@ -310,6 +310,7 @@ function GUI(props: GUIProps) {
   // } as any);
 
   const [showFeedbackDialog, setShowFeedbackDialog] = useState(false);
+  const [feedbackDialogMessage, setFeedbackDialogMessage] = useState("");
 
   const topGuiDivRef = useRef<HTMLDivElement>(null);
   const client = useContinueGUIProtocol();
@@ -458,6 +459,7 @@ function GUI(props: GUIProps) {
         onClose={() => {
           setShowFeedbackDialog(false);
         }}
+        message={feedbackDialogMessage}
       ></TextDialog>
 
       <TopGUIDiv
@@ -593,17 +595,24 @@ function GUI(props: GUIProps) {
         </div>
         <HeaderButtonWithText
           onClick={() => {
-            client?.changeDefaultModel(
-              usingFastModel ? "gpt-4" : "gpt-3.5-turbo"
-            );
+            // client?.changeDefaultModel(
+            //   usingFastModel ? "gpt-4" : "gpt-3.5-turbo"
+            // );
+            if (!usingFastModel) {
+              // Show the dialog
+              setFeedbackDialogMessage(
+                "We don't yet support local models, but we're working on it! If privacy is a concern of yours, please use the feedback button in the bottom right to let us know."
+              );
+              setShowFeedbackDialog(true);
+            }
             setUsingFastModel((prev) => !prev);
           }}
-          text={usingFastModel ? "gpt-3.5-turbo" : "gpt-4"}
+          text={usingFastModel ? "local" : "gpt-4"}
         >
           <div
             style={{ fontSize: "18px", marginLeft: "2px", marginRight: "2px" }}
           >
-            {usingFastModel ? "⚡" : "🧠"}
+            {usingFastModel ? "🔒" : "🧠"}
           </div>
         </HeaderButtonWithText>
         <HeaderButtonWithText
@@ -625,6 +634,9 @@ function GUI(props: GUIProps) {
         <HeaderButtonWithText
           onClick={() => {
             // Set dialog open
+            setFeedbackDialogMessage(
+              "Having trouble using Continue? Want a new feature? Let us know! This box is anonymous, but we will promptly address your feedback."
+            );
             setShowFeedbackDialog(true);
           }}
           text="Feedback"
-- 
cgit v1.2.3-70-g09d2


From 6b1a6fd5ab2224cb02a7918eccf1a7f01cfe7fde Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Sun, 2 Jul 2023 18:04:55 -0700
Subject: chat output fixes

---
 continuedev/src/continuedev/steps/chat.py      | 12 +++++++++
 continuedev/src/continuedev/steps/core/core.py | 34 ++++++++++++++++++--------
 2 files changed, 36 insertions(+), 10 deletions(-)

(limited to 'continuedev/src')

diff --git a/continuedev/src/continuedev/steps/chat.py b/continuedev/src/continuedev/steps/chat.py
index 2efef37d..34a97a17 100644
--- a/continuedev/src/continuedev/steps/chat.py
+++ b/continuedev/src/continuedev/steps/chat.py
@@ -21,6 +21,7 @@ openai.api_key = OPENAI_API_KEY
 class SimpleChatStep(Step):
     user_input: str
     name: str = "Chat"
+    manage_own_chat_context: bool = True
 
     async def run(self, sdk: ContinueSDK):
         self.description = f"`{self.user_input}`\n\n"
@@ -36,17 +37,28 @@ class SimpleChatStep(Step):
             summary=self.user_input
         ))
 
+        completion = ""
         async for chunk in sdk.models.gpt4.stream_chat(messages):
             if sdk.current_step_was_deleted():
                 return
 
             if "content" in chunk:
                 self.description += chunk["content"]
+                completion += chunk["content"]
                 await sdk.update_ui()
 
         self.name = (await sdk.models.gpt35.complete(
             f"Write a short title for the following chat message: {self.description}")).strip()
 
+        if self.name.startswith('"') and self.name.endswith('"'):
+            self.name = self.name[1:-1]
+
+        self.chat_context.append(ChatMessage(
+            role="assistant",
+            content=completion,
+            summary=self.name
+        ))
+
 
 class AddFileStep(Step):
     name: str = "Add File"
diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py
index 345d99bc..f7b64a45 100644
--- a/continuedev/src/continuedev/steps/core/core.py
+++ b/continuedev/src/continuedev/steps/core/core.py
@@ -154,19 +154,26 @@ class DefaultModelEditCodeStep(Step):
 
     _prompt_and_completion: str = ""
 
-    async def describe(self, models: Models) -> Coroutine[str, None, None]:
-        description = await models.gpt3516k.complete(
-            f"{self._prompt_and_completion}\n\nPlease give brief a description of the changes made above using markdown bullet points. Be concise and only mention changes made to the commit before, not prefix or suffix:")
-        self.name = await models.gpt3516k.complete(f"Write a very short title to describe this requested change (no quotes): '{self.user_input}'. This is the title:")
+    def _cleanup_output(self, output: str) -> str:
+        output = output.replace('\\"', '"')
+        output = output.replace("\\'", "'")
+        output = output.replace("\\n", "\n")
+        output = output.replace("\\t", "\t")
+        output = output.replace("\\\\", "\\")
+        if output.startswith('"') and output.endswith('"'):
+            output = output[1:-1]
 
-        # Remove quotes from title and description if they are wrapped
-        if description.startswith('"') and description.endswith('"'):
-            description = description[1:-1]
+        return output
 
-        if self.name.startswith('"') and self.name.endswith('"'):
-            self.name = self.name[1:-1]
+    async def describe(self, models: Models) -> Coroutine[str, None, None]:
+        description = await models.gpt3516k.complete(dedent(f"""\
+            {self._prompt_and_completion}
+            
+            Please give brief a description of the changes made above using markdown bullet points. Be concise and only mention changes made to the commit before, not prefix or suffix:"""))
+        name = await models.gpt3516k.complete(f"Write a very short title to describe this requested change (no quotes): '{self.user_input}'. This is the title:")
+        self.name = self._cleanup_output(name)
 
-        return f"`{self.user_input}`\n\n" + description
+        return f"`{self.user_input}`\n\n{self._cleanup_output(description)}"
 
     async def get_prompt_parts(self, rif: RangeInFileWithContents, sdk: ContinueSDK, full_file_contents: str):
         # We don't know here all of the functions being passed in.
@@ -586,10 +593,17 @@ class UserInputStep(Step):
     name: str = "User Input"
     hide: bool = True
 
+    manage_own_chat_context: bool = True
+
     async def describe(self, models: Models) -> Coroutine[str, None, None]:
         return self.user_input
 
     async def run(self, sdk: ContinueSDK) -> Coroutine[UserInputObservation, None, None]:
+        self.chat_context.append(ChatMessage(
+            role="user",
+            content=self.user_input,
+            summary=self.user_input
+        ))
         return UserInputObservation(user_input=self.user_input)
 
 
-- 
cgit v1.2.3-70-g09d2


From a1cdf04b3e75ce46ab06e905f8e139d2a6ebc884 Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Sun, 2 Jul 2023 18:23:46 -0700
Subject: solved streaming off-by-one issue

---
 continuedev/src/continuedev/core/sdk.py         | 2 +-
 continuedev/src/continuedev/libs/util/dedent.py | 6 ++++++
 continuedev/src/continuedev/steps/core/core.py  | 7 +++----
 3 files changed, 10 insertions(+), 5 deletions(-)

(limited to 'continuedev/src')

diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py
index d95a233f..cfe2e436 100644
--- a/continuedev/src/continuedev/core/sdk.py
+++ b/continuedev/src/continuedev/core/sdk.py
@@ -199,7 +199,7 @@ class ContinueSDK(AbstractContinueSDK):
 
             # Don't insert after latest user message or function call
             i = -1
-            if history_context[i].role == "user" or history_context[i].role == "function":
+            if len(history_context) > 0 and (history_context[i].role == "user" or history_context[i].role == "function"):
                 i -= 1
             history_context.insert(i, msg)
 
diff --git a/continuedev/src/continuedev/libs/util/dedent.py b/continuedev/src/continuedev/libs/util/dedent.py
index bbbeba5e..87876d4b 100644
--- a/continuedev/src/continuedev/libs/util/dedent.py
+++ b/continuedev/src/continuedev/libs/util/dedent.py
@@ -8,8 +8,14 @@ def dedent_and_get_common_whitespace(s: str) -> Tuple[str, str]:
 
     # Longest common whitespace prefix
     lcp = lines[0].split(lines[0].strip())[0]
+    # Iterate through the lines
     for i in range(1, len(lines)):
+        # Empty lines are wildcards
+        if lines[i].strip() == "":
+            continue
+        # Iterate through the leading whitespace characters of the current line
         for j in range(0, len(lcp)):
+            # If it doesn't have the same whitespace as lcp, then update lcp
             if j >= len(lines[i]) or lcp[j] != lines[i][j]:
                 lcp = lcp[:j]
                 if lcp == "":
diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py
index f7b64a45..8f59bc4d 100644
--- a/continuedev/src/continuedev/steps/core/core.py
+++ b/continuedev/src/continuedev/steps/core/core.py
@@ -368,7 +368,7 @@ class DefaultModelEditCodeStep(Step):
 
                 # Insert the suggestion
                 replacement = "\n".join(current_block_lines)
-                start_line = current_block_start + 1
+                start_line = current_block_start
                 end_line = current_block_start + index_of_last_line_in_block
                 await sdk.ide.showSuggestion(FileEdit(
                     filepath=rif.filepath,
@@ -376,10 +376,9 @@ class DefaultModelEditCodeStep(Step):
                         start_line, 0, end_line, 0),
                     replacement=replacement
                 ))
-                if replacement == "":
-                    current_line_in_file += 1
 
                 # Reset current block / update variables
+                current_line_in_file += 1
                 offset_from_blocks += len(current_block_lines)
                 original_lines_below_previous_blocks = original_lines_below_previous_blocks[
                     index_of_last_line_in_block + 1:]
@@ -501,7 +500,7 @@ class DefaultModelEditCodeStep(Step):
             await sdk.ide.showSuggestion(FileEdit(
                 filepath=rif.filepath,
                 range=Range.from_shorthand(
-                    current_block_start + 1, 0, current_block_start + len(original_lines_below_previous_blocks), 0),
+                    current_block_start, 0, current_block_start + len(original_lines_below_previous_blocks), 0),
                 replacement="\n".join(current_block_lines)
             ))
 
-- 
cgit v1.2.3-70-g09d2


From 80627c7f6ee504ebc308ead92d1963f6210b098c Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Sun, 2 Jul 2023 18:31:54 -0700
Subject: create new file to edit if no ranges selected

---
 continuedev/src/continuedev/steps/main.py | 7 +++++++
 1 file changed, 7 insertions(+)

(limited to 'continuedev/src')

diff --git a/continuedev/src/continuedev/steps/main.py b/continuedev/src/continuedev/steps/main.py
index def1af4e..3cf78c40 100644
--- a/continuedev/src/continuedev/steps/main.py
+++ b/continuedev/src/continuedev/steps/main.py
@@ -266,6 +266,13 @@ class EditHighlightedCodeStep(Step):
             range_in_files = [RangeInFile.from_entire_file(
                 filepath, content) for filepath, content in contents.items()]
 
+        # If still no highlighted code, create a new file and edit there
+        if len(range_in_files) == 0:
+            # Create a new file
+            new_file_path = "new_file.txt"
+            await sdk.add_file(new_file_path)
+            range_in_files = [RangeInFile.from_entire_file(new_file_path, "")]
+
         await sdk.run_step(DefaultModelEditCodeStep(user_input=self.user_input, range_in_files=range_in_files))
 
 
-- 
cgit v1.2.3-70-g09d2