Skip to content

Commit 73d1e92

Browse files
manually install the extension from the registery
1 parent 574e1b5 commit 73d1e92

File tree

2 files changed

+160
-37
lines changed

2 files changed

+160
-37
lines changed

codeflash/cli_cmds/cmd_init.py

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import ast
44
import os
55
import re
6-
import shutil
76
import subprocess
87
import sys
98
from enum import Enum, auto
@@ -24,7 +23,8 @@
2423

2524
from codeflash.api.cfapi import is_github_app_installed_on_repo
2625
from codeflash.cli_cmds.cli_common import apologize_and_exit
27-
from codeflash.cli_cmds.console import console, logger, progress_bar
26+
from codeflash.cli_cmds.console import console, logger
27+
from codeflash.cli_cmds.vscode import install_vscode_extension
2828
from codeflash.code_utils.compat import LF
2929
from codeflash.code_utils.config_parser import parse_config_file
3030
from codeflash.code_utils.env_utils import check_formatter_installed, get_codeflash_api_key
@@ -805,41 +805,6 @@ def install_github_actions(override_formatter_check: bool = False) -> None: # n
805805
apologize_and_exit()
806806

807807

808-
def install_vscode_extension() -> None:
809-
vscode_path = shutil.which("code")
810-
if not vscode_path:
811-
return
812-
813-
error = ""
814-
with progress_bar("Installing Codeflash for VSCode…"):
815-
try:
816-
result = subprocess.run(
817-
[vscode_path, "--install-extension", "codeflash.codeflash", "--force"],
818-
check=True,
819-
text=True,
820-
timeout=60,
821-
capture_output=True,
822-
)
823-
except subprocess.TimeoutExpired:
824-
error = "Installation timed out."
825-
except subprocess.CalledProcessError as e:
826-
error = e.stderr or "Unknown error."
827-
828-
if error:
829-
ph("vscode-extension-install-failed", {"error": error.strip()})
830-
click.echo(
831-
"Failed to install Codeflash for VSCode. Please try installing it manually from the Marketplace: https://marketplace.visualstudio.com/items?itemName=codeflash.codeflash"
832-
)
833-
click.echo(error.strip())
834-
else:
835-
output = (result.stdout or "").lower()
836-
if "already installed" in output:
837-
click.echo("✅ Codeflash for VSCode is already installed.")
838-
return
839-
ph("vscode-extension-installed")
840-
click.echo("✅ Installed the latest version of Codeflash for VSCode.")
841-
842-
843808
def determine_dependency_manager(pyproject_data: dict[str, Any]) -> DependencyManager: # noqa: PLR0911
844809
"""Determine which dependency manager is being used based on pyproject.toml contents."""
845810
if (Path.cwd() / "poetry.lock").exists():

codeflash/cli_cmds/vscode.py

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import json
2+
import shutil
3+
import subprocess
4+
import tempfile
5+
import time
6+
import zipfile
7+
from functools import lru_cache
8+
from pathlib import Path
9+
from typing import Any
10+
11+
import click
12+
import requests
13+
14+
from codeflash.cli_cmds.console import logger, progress_bar
15+
from codeflash.telemetry.posthog_cf import ph
16+
17+
18+
@lru_cache(maxsize=1)
19+
def get_extension_info() -> dict[str, Any]:
20+
url = "https://open-vsx.org/api/codeflash/codeflash/latest"
21+
try:
22+
response = requests.get(url, timeout=60)
23+
response.raise_for_status()
24+
return response.json()
25+
except Exception as e:
26+
logger.error("Failed to get extension metadata from open-vsx.org: %s", e)
27+
return {}
28+
29+
30+
def download_extension_artifacts(vscode_path: Path) -> bool:
31+
if not (vscode_path / "extensions").exists():
32+
logger.warning("VSCode extensions directory does not exist")
33+
return False
34+
35+
info = get_extension_info()
36+
download_url = info.get("files", {}).get("download", "")
37+
latest_version = info.get("version", "")
38+
if not download_url:
39+
return False
40+
41+
with tempfile.TemporaryDirectory() as tmpdir:
42+
zip_path = Path(tmpdir) / "cf-archive.zip"
43+
44+
resp = requests.get(download_url, stream=True, timeout=60)
45+
resp.raise_for_status()
46+
with zip_path.open("wb") as f:
47+
for chunk in resp.iter_content(chunk_size=8192):
48+
f.write(chunk)
49+
50+
with zipfile.ZipFile(zip_path, "r") as zf:
51+
zf.extractall(tmpdir)
52+
53+
extension_path = Path(tmpdir) / "extension"
54+
if not extension_path.is_dir():
55+
logger.warning("No 'extension' folder found in archive")
56+
return False
57+
58+
dest_path = vscode_path / "extensions" / f"codeflash.codeflash-{latest_version}"
59+
60+
if dest_path.exists():
61+
shutil.rmtree(dest_path) # cleanup if exists
62+
shutil.copytree(extension_path, dest_path)
63+
return True
64+
65+
66+
def write_cf_extension_metadata(vscode_path: Path, editor: str, version: str) -> bool:
67+
metadata_file = vscode_path / "extensions" / "extensions.json"
68+
if not metadata_file.exists():
69+
logger.warning("%s extensions metadata file does not exist", editor)
70+
return False
71+
72+
data = {
73+
"identifier": {"id": "codeflash.codeflash", "uuid": "7798581f-9eab-42be-a1b2-87f90973434d"},
74+
"version": version,
75+
"location": {"$mid": 1, "path": f"{vscode_path}/extensions/codeflash.codeflash-{version}", "scheme": "file"},
76+
"relativeLocation": f"codeflash.codeflash-{version}",
77+
"metadata": {
78+
"installedTimestamp": int(time.time() * 1000),
79+
"pinned": False,
80+
"source": "gallery",
81+
"id": "7798581f-9eab-42be-a1b2-87f90973434d",
82+
"publisherId": "bc13551d-2729-4c35-84ce-1d3bd3baab45",
83+
"publisherDisplayName": "CodeFlash",
84+
"targetPlatform": "universal",
85+
"updated": True,
86+
"isPreReleaseVersion": False,
87+
"hasPreReleaseVersion": False,
88+
"isApplicationScoped": False,
89+
"isMachineScoped": False,
90+
"isBuiltin": False,
91+
"private": False,
92+
"preRelease": False,
93+
},
94+
}
95+
with metadata_file.open("r", encoding="utf-8") as f:
96+
metadata = json.load(f)
97+
metadata = [entry for entry in metadata if entry.get("identifier", {}).get("id") != data["identifier"]["id"]]
98+
metadata.append(data)
99+
with metadata_file.open("w", encoding="utf-8") as f:
100+
json.dump(metadata, f)
101+
return True
102+
103+
104+
def manual_install_vscode_extension(dest_path: Path, editor: str = "VSCode") -> None:
105+
installed = False
106+
with progress_bar(f"Manually installing Codeflash for {editor} from open-vsx.org…"):
107+
try:
108+
did_download = download_extension_artifacts(dest_path)
109+
if did_download:
110+
info = get_extension_info()
111+
latest_version = info.get("version", "")
112+
did_write_metadata = write_cf_extension_metadata(dest_path, editor, latest_version)
113+
if did_write_metadata:
114+
installed = True
115+
except Exception as e:
116+
logger.error("Failed to install Codeflash for %s: %s", editor, e)
117+
if installed:
118+
click.echo(f"✅ Installed the latest version of Codeflash for {editor}.")
119+
120+
121+
def install_vscode_extension() -> None:
122+
# cursor_path = Path(Path.home()) / ".cursor"
123+
# windsurf_path = Path(Path.home()) / ".windsurf"
124+
125+
vscode_path = shutil.which("code")
126+
if not vscode_path:
127+
vscode_path = Path(Path.home()) / ".vscode"
128+
manual_install_vscode_extension(vscode_path)
129+
return
130+
131+
error = ""
132+
with progress_bar("Installing Codeflash for VSCode…"):
133+
try:
134+
result = subprocess.run(
135+
[vscode_path, "--install-extension", "codeflash.codeflash", "--force"],
136+
check=True,
137+
text=True,
138+
timeout=60,
139+
capture_output=True,
140+
)
141+
except subprocess.TimeoutExpired:
142+
error = "Installation timed out."
143+
except subprocess.CalledProcessError as e:
144+
error = e.stderr or "Unknown error."
145+
146+
if error:
147+
ph("vscode-extension-install-failed", {"error": error.strip()})
148+
click.echo(
149+
"Failed to install Codeflash for VSCode. Please try installing it manually from the Marketplace: https://marketplace.visualstudio.com/items?itemName=codeflash.codeflash"
150+
)
151+
click.echo(error.strip())
152+
else:
153+
output = (result.stdout or "").lower()
154+
if "already installed" in output:
155+
click.echo("✅ Codeflash for VSCode is already installed.")
156+
return
157+
ph("vscode-extension-installed")
158+
click.echo("✅ Installed the latest version of Codeflash for VSCode.")

0 commit comments

Comments
 (0)