summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--continuedev/src/continuedev/libs/util/paths.py6
-rw-r--r--continuedev/src/continuedev/plugins/context_providers/file.py2
-rw-r--r--continuedev/src/continuedev/server/ide.py12
-rw-r--r--continuedev/src/continuedev/server/ide_protocol.py4
-rw-r--r--continuedev/src/continuedev/server/meilisearch_server.py67
-rw-r--r--extension/src/activation/environmentSetup.ts35
-rw-r--r--extension/src/continueIdeClient.ts89
7 files changed, 135 insertions, 80 deletions
diff --git a/continuedev/src/continuedev/libs/util/paths.py b/continuedev/src/continuedev/libs/util/paths.py
index b3e9ecc1..9f3117d0 100644
--- a/continuedev/src/continuedev/libs/util/paths.py
+++ b/continuedev/src/continuedev/libs/util/paths.py
@@ -31,6 +31,12 @@ def getServerFolderPath():
return path
+def getMeilisearchExePath():
+ binary_name = "meilisearch.exe" if os.name == "nt" else "meilisearch"
+ path = os.path.join(getServerFolderPath(), binary_name)
+ return path
+
+
def getSessionFilePath(session_id: str):
path = os.path.join(getSessionsFolderPath(), f"{session_id}.json")
os.makedirs(os.path.dirname(path), exist_ok=True)
diff --git a/continuedev/src/continuedev/plugins/context_providers/file.py b/continuedev/src/continuedev/plugins/context_providers/file.py
index 9846dd3e..859088b8 100644
--- a/continuedev/src/continuedev/plugins/context_providers/file.py
+++ b/continuedev/src/continuedev/plugins/context_providers/file.py
@@ -123,7 +123,7 @@ class FileContextProvider(ContextProvider):
)
async def provide_context_items(self, workspace_dir: str) -> List[ContextItem]:
- contents = await self.sdk.ide.listDirectoryContents(workspace_dir)
+ contents = await self.sdk.ide.listDirectoryContents(workspace_dir, True)
if contents is None:
return []
diff --git a/continuedev/src/continuedev/server/ide.py b/continuedev/src/continuedev/server/ide.py
index 8a62c39e..89fcd0d1 100644
--- a/continuedev/src/continuedev/server/ide.py
+++ b/continuedev/src/continuedev/server/ide.py
@@ -494,10 +494,12 @@ class IdeProtocolServer(AbstractIdeProtocolServer):
)
return resp.fileEdit
- async def listDirectoryContents(self, directory: str) -> List[str]:
+ async def listDirectoryContents(
+ self, directory: str, recursive: bool = False
+ ) -> List[str]:
"""List the contents of a directory"""
resp = await self._send_and_receive_json(
- {"directory": directory},
+ {"directory": directory, "recursive": recursive},
ListDirectoryContentsResponse,
"listDirectoryContents",
)
@@ -574,7 +576,11 @@ async def websocket_endpoint(websocket: WebSocket, session_id: str = None):
# Start meilisearch
try:
- await start_meilisearch()
+
+ async def on_err(e):
+ logger.debug(f"Failed to start MeiliSearch: {e}")
+
+ create_async_task(start_meilisearch(), on_err)
except Exception as e:
logger.debug("Failed to start MeiliSearch")
logger.debug(e)
diff --git a/continuedev/src/continuedev/server/ide_protocol.py b/continuedev/src/continuedev/server/ide_protocol.py
index 4ef4bde7..2a07ae2a 100644
--- a/continuedev/src/continuedev/server/ide_protocol.py
+++ b/continuedev/src/continuedev/server/ide_protocol.py
@@ -148,7 +148,9 @@ class AbstractIdeProtocolServer(ABC):
"""Called when a file is saved"""
@abstractmethod
- async def listDirectoryContents(self, directory: str) -> List[str]:
+ async def listDirectoryContents(
+ self, directory: str, recursive: bool = False
+ ) -> List[str]:
"""List directory contents"""
@abstractmethod
diff --git a/continuedev/src/continuedev/server/meilisearch_server.py b/continuedev/src/continuedev/server/meilisearch_server.py
index 037ce8fa..390eeb50 100644
--- a/continuedev/src/continuedev/server/meilisearch_server.py
+++ b/continuedev/src/continuedev/server/meilisearch_server.py
@@ -3,20 +3,59 @@ import os
import shutil
import subprocess
+import aiofiles
+import aiohttp
from meilisearch_python_async import Client
from ..libs.util.logging import logger
-from ..libs.util.paths import getServerFolderPath
+from ..libs.util.paths import getMeilisearchExePath, getServerFolderPath
-def ensure_meilisearch_installed() -> bool:
+async def download_file(url: str, filename: str):
+ async with aiohttp.ClientSession() as session:
+ async with session.get(url) as resp:
+ if resp.status == 200:
+ f = await aiofiles.open(filename, mode="wb")
+ await f.write(await resp.read())
+ await f.close()
+
+
+async def download_meilisearch():
+ """
+ Downloads MeiliSearch.
+ """
+
+ serverPath = getServerFolderPath()
+ logger.debug("Downloading MeiliSearch...")
+
+ if os.name == "nt":
+ download_url = "https://github.com/meilisearch/meilisearch/releases/download/v1.3.2/meilisearch-windows-amd64.exe"
+ download_path = getMeilisearchExePath()
+ if not os.path.exists(download_path):
+ await download_file(download_url, download_path)
+ # subprocess.run(
+ # f"curl -L {download_url} -o {download_path}",
+ # shell=True,
+ # check=True,
+ # cwd=serverPath,
+ # )
+ else:
+ subprocess.run(
+ "curl -L https://install.meilisearch.com | sh",
+ shell=True,
+ check=True,
+ cwd=serverPath,
+ )
+
+
+async def ensure_meilisearch_installed() -> bool:
"""
Checks if MeiliSearch is installed.
Returns a bool indicating whether it was installed to begin with.
"""
serverPath = getServerFolderPath()
- meilisearchPath = os.path.join(serverPath, "meilisearch")
+ meilisearchPath = getMeilisearchExePath()
dumpsPath = os.path.join(serverPath, "dumps")
dataMsPath = os.path.join(serverPath, "data.ms")
@@ -40,14 +79,7 @@ def ensure_meilisearch_installed() -> bool:
for p in existing_paths:
shutil.rmtree(p, ignore_errors=True)
- # Download MeiliSearch
- logger.debug("Downloading MeiliSearch...")
- subprocess.run(
- "curl -L https://install.meilisearch.com | sh",
- shell=True,
- check=True,
- cwd=serverPath,
- )
+ await download_meilisearch()
return False
@@ -66,7 +98,7 @@ async def check_meilisearch_running() -> bool:
if resp.status != "available":
return False
return True
- except Exception as e:
+ except Exception:
return False
except Exception:
return False
@@ -86,24 +118,21 @@ async def start_meilisearch():
"""
Starts the MeiliSearch server, wait for it.
"""
-
- # Doesn't work on windows for now
- if not os.name == "posix":
- return
-
serverPath = getServerFolderPath()
# Check if MeiliSearch is installed, if not download
- was_already_installed = ensure_meilisearch_installed()
+ was_already_installed = await ensure_meilisearch_installed()
# Check if MeiliSearch is running
if not await check_meilisearch_running() or not was_already_installed:
logger.debug("Starting MeiliSearch...")
+ binary_name = "meilisearch" if os.name == "nt" else "./meilisearch"
subprocess.Popen(
- ["./meilisearch", "--no-analytics"],
+ [binary_name, "--no-analytics"],
cwd=serverPath,
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT,
close_fds=True,
start_new_session=True,
+ shell=True
)
diff --git a/extension/src/activation/environmentSetup.ts b/extension/src/activation/environmentSetup.ts
index 7ca87768..3aa536d0 100644
--- a/extension/src/activation/environmentSetup.ts
+++ b/extension/src/activation/environmentSetup.ts
@@ -74,6 +74,14 @@ function serverVersionPath(): string {
return path.join(serverPath(), "server_version.txt");
}
+function serverBinaryPath(): string {
+ return path.join(
+ serverPath(),
+ "exe",
+ `run${os.platform() === "win32" ? ".exe" : ""}`
+ );
+}
+
export function getExtensionVersion() {
const extension = vscode.extensions.getExtension("continue.continue");
return extension?.packageJSON.version || "";
@@ -105,14 +113,7 @@ async function checkOrKillRunningServer(serverUrl: string): Promise<boolean> {
// Try again, on Windows. This time with taskkill
if (os.platform() === "win32") {
try {
- const exePath = path.join(
- getExtensionUri().fsPath,
- "server",
- "exe",
- "run.exe"
- );
-
- await runCommand(`taskkill /F /IM ${exePath}`);
+ await runCommand(`taskkill /F /IM run.exe`);
} catch (e: any) {
console.log(
"Failed to kill old server second time on windows with taskkill:",
@@ -126,14 +127,9 @@ async function checkOrKillRunningServer(serverUrl: string): Promise<boolean> {
fs.unlinkSync(serverVersionPath());
}
// Also delete the server binary
- const serverBinaryPath = path.join(
- getExtensionUri().fsPath,
- "server",
- "exe",
- `run${os.platform() === "win32" ? ".exe" : ""}`
- );
- if (fs.existsSync(serverBinaryPath)) {
- fs.unlinkSync(serverBinaryPath);
+ const serverBinary = serverBinaryPath();
+ if (fs.existsSync(serverBinary)) {
+ fs.unlinkSync(serverBinary);
}
}
@@ -213,12 +209,7 @@ export async function startContinuePythonServer(redownload: boolean = true) {
: "mac/run"
: "linux/run";
- const destination = path.join(
- getExtensionUri().fsPath,
- "server",
- "exe",
- `run${os.platform() === "win32" ? ".exe" : ""}`
- );
+ const destination = serverBinaryPath();
// First, check if the server is already downloaded
let shouldDownload = true;
diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts
index 94997d76..353584e9 100644
--- a/extension/src/continueIdeClient.ts
+++ b/extension/src/continueIdeClient.ts
@@ -272,40 +272,10 @@ class IdeProtocolClient {
break;
case "listDirectoryContents":
messenger.send("listDirectoryContents", {
- contents: (
- await vscode.workspace.fs.readDirectory(
- uriFromFilePath(data.directory)
- )
- )
- .map(([name, type]) => name)
- .filter((name) => {
- const DEFAULT_IGNORE_DIRS = [
- ".git",
- ".vscode",
- ".idea",
- ".vs",
- ".venv",
- "env",
- ".env",
- "node_modules",
- "dist",
- "build",
- "target",
- "out",
- "bin",
- ".pytest_cache",
- ".vscode-test",
- ".continue",
- "__pycache__",
- ];
- if (
- !DEFAULT_IGNORE_DIRS.some((dir) =>
- name.split(path.sep).includes(dir)
- )
- ) {
- return name;
- }
- }),
+ contents: await this.getDirectoryContents(
+ data.directory,
+ data.recursive || false
+ ),
});
break;
case "editFile":
@@ -562,6 +532,57 @@ class IdeProtocolClient {
});
}
+ async getDirectoryContents(
+ directory: string,
+ recursive: boolean
+ ): Promise<string[]> {
+ let nameAndType = (
+ await vscode.workspace.fs.readDirectory(uriFromFilePath(directory))
+ ).filter(([name, type]) => {
+ const DEFAULT_IGNORE_DIRS = [
+ ".git",
+ ".vscode",
+ ".idea",
+ ".vs",
+ ".venv",
+ "env",
+ ".env",
+ "node_modules",
+ "dist",
+ "build",
+ "target",
+ "out",
+ "bin",
+ ".pytest_cache",
+ ".vscode-test",
+ ".continue",
+ "__pycache__",
+ ];
+ if (
+ !DEFAULT_IGNORE_DIRS.some((dir) => name.split(path.sep).includes(dir))
+ ) {
+ return name;
+ }
+ });
+
+ let absolutePaths = nameAndType
+ .filter(([name, type]) => type === vscode.FileType.File)
+ .map(([name, type]) => path.join(directory, name));
+ if (recursive) {
+ for (const [name, type] of nameAndType) {
+ if (type === vscode.FileType.Directory) {
+ const subdirectory = path.join(directory, name);
+ const subdirectoryContents = await this.getDirectoryContents(
+ subdirectory,
+ recursive
+ );
+ absolutePaths = absolutePaths.concat(subdirectoryContents);
+ }
+ }
+ }
+ return absolutePaths;
+ }
+
async readFile(filepath: string): Promise<string> {
let contents: string | undefined;
if (typeof contents === "undefined") {