summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--continuedev/src/continuedev/core/env.py10
-rw-r--r--continuedev/src/continuedev/core/sdk.py37
-rw-r--r--continuedev/src/continuedev/models/filesystem_edit.py4
-rw-r--r--continuedev/src/continuedev/models/main.py8
-rw-r--r--extension/react-app/src/components/StepContainer.tsx8
5 files changed, 53 insertions, 14 deletions
diff --git a/continuedev/src/continuedev/core/env.py b/continuedev/src/continuedev/core/env.py
index edd3297c..2692c348 100644
--- a/continuedev/src/continuedev/core/env.py
+++ b/continuedev/src/continuedev/core/env.py
@@ -7,11 +7,15 @@ def get_env_var(var_name: str):
return os.getenv(var_name)
-def save_env_var(var_name: str, var_value: str):
+def make_sure_env_exists():
if not os.path.exists('.env'):
with open('.env', 'w') as f:
- f.write(f'{var_name}="{var_value}"\n')
- return
+ f.write('')
+
+
+def save_env_var(var_name: str, var_value: str):
+ make_sure_env_exists()
+
with open('.env', 'r') as f:
lines = f.readlines()
with open('.env', 'w') as f:
diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py
index b9b20422..ce0c53fd 100644
--- a/continuedev/src/continuedev/core/sdk.py
+++ b/continuedev/src/continuedev/core/sdk.py
@@ -2,7 +2,7 @@ import os
from typing import Coroutine, Union
from .config import ContinueConfig, load_config
-from ..models.filesystem_edit import FileSystemEdit, AddFile, DeleteFile, AddDirectory, DeleteDirectory
+from ..models.filesystem_edit import FileEdit, FileSystemEdit, AddFile, DeleteFile, AddDirectory, DeleteDirectory
from ..models.filesystem import RangeInFile
from ..libs.llm import LLM
from ..libs.llm.hf_inference_api import HuggingFaceInferenceAPI
@@ -11,7 +11,7 @@ from .observation import Observation
from ..server.ide_protocol import AbstractIdeProtocolServer
from .main import History, Step
from ..libs.steps.core.core import *
-from .env import get_env_var, save_env_var
+from .env import get_env_var, make_sure_env_exists
class Agent:
@@ -29,12 +29,12 @@ class Models:
async def starcoder(self):
api_key = await self.sdk.get_user_secret(
- 'HUGGING_FACE_TOKEN', 'Please enter your Hugging Face token')
+ 'HUGGING_FACE_TOKEN', 'Please add your Hugging Face token to the .env file')
return HuggingFaceInferenceAPI(api_key=api_key)
async def gpt35(self):
api_key = await self.sdk.get_user_secret(
- 'OPENAI_API_KEY', 'Please enter your OpenAI API key')
+ 'OPENAI_API_KEY', 'Please add your OpenAI API key to the .env file')
return OpenAI(api_key=api_key, default_model="gpt-3.5-turbo")
@@ -86,6 +86,12 @@ class ContinueSDK:
prompt=f'Here is the code before:\n\n{{code}}\n\nHere is the user request:\n\n{prompt}\n\nHere is the code edited to perfectly solve the user request:\n\n'
))
+ async def append_to_file(self, filename: str, content: str):
+ filepath = await self._ensure_absolute_path(filename)
+ previous_content = await self.ide.readFile(filepath)
+ file_edit = FileEdit.from_append(filepath, previous_content, content)
+ await self.ide.applyFileSystemEdit(file_edit)
+
async def add_file(self, filename: str, content: str | None):
return await self.run_step(FileSystemEditStep(edit=AddFile(filename=filename, content=content)))
@@ -99,14 +105,23 @@ class ContinueSDK:
return await self.run_step(FileSystemEditStep(edit=DeleteDirectory(path=path)))
async def get_user_secret(self, env_var: str, prompt: str) -> str:
- try:
+ make_sure_env_exists()
+
+ val = None
+ while val is None:
+ try:
+ val = get_env_var(env_var)
+ if val is not None:
+ return val
+ except:
+ pass
+ server_dir = os.getcwd()
+ env_path = os.path.join(server_dir, ".env")
+ await self.ide.setFileOpen(env_path)
+ await self.append_to_file(env_path, f'\n{env_var}="<ENTER SECRET HERE>"')
+ await self.run_step(WaitForUserConfirmationStep(prompt=prompt))
val = get_env_var(env_var)
- if val is not None:
- return val
- except:
- pass
- val = (await self.run_step(WaitForUserInputStep(prompt=prompt))).text
- save_env_var(env_var, val)
+
return val
async def get_config(self) -> ContinueConfig:
diff --git a/continuedev/src/continuedev/models/filesystem_edit.py b/continuedev/src/continuedev/models/filesystem_edit.py
index 7526d4c9..8e74b819 100644
--- a/continuedev/src/continuedev/models/filesystem_edit.py
+++ b/continuedev/src/continuedev/models/filesystem_edit.py
@@ -37,6 +37,10 @@ class FileEdit(AtomicFileSystemEdit):
def from_insertion(filepath: str, position: Position, content: str) -> "FileEdit":
return FileEdit(filepath=filepath, range=Range.from_shorthand(position.line, position.character, position.line, position.character), replacement=content)
+ @staticmethod
+ def from_append(filepath: str, previous_content: str, appended_content: str) -> "FileEdit":
+ return FileEdit(filepath=filepath, range=Range.from_position(Position.from_end_of_file(previous_content)), replacement=appended_content)
+
class FileEditWithFullContents(BaseModel):
fileEdit: FileEdit
diff --git a/continuedev/src/continuedev/models/main.py b/continuedev/src/continuedev/models/main.py
index 1bc51ff1..02c44aae 100644
--- a/continuedev/src/continuedev/models/main.py
+++ b/continuedev/src/continuedev/models/main.py
@@ -39,6 +39,10 @@ class Position(BaseModel):
return Position(line=line, character=character)
+ @staticmethod
+ def from_end_of_file(contents: str) -> "Position":
+ return Position.from_index(contents, len(contents))
+
class Range(BaseModel):
"""A range in a file. 0-indexed."""
@@ -117,6 +121,10 @@ class Range(BaseModel):
return Range.from_shorthand(start_line, 0, end_line, len(content_lines[end_line]) - 1)
+ @staticmethod
+ def from_position(position: Position) -> "Range":
+ return Range(start=position, end=position)
+
class AbstractModel(ABC, BaseModel):
@root_validator(pre=True)
diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx
index ec601ea7..5e979b34 100644
--- a/extension/react-app/src/components/StepContainer.tsx
+++ b/extension/react-app/src/components/StepContainer.tsx
@@ -80,6 +80,13 @@ function StepContainer(props: StepContainerProps) {
const [open, setOpen] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const naturalLanguageInputRef = useRef<HTMLTextAreaElement>(null);
+ const userInputRef = useRef<HTMLInputElement>(null);
+
+ useEffect(() => {
+ if (userInputRef?.current) {
+ userInputRef.current.focus();
+ }
+ }, [userInputRef]);
useEffect(() => {
if (isHovered) {
@@ -136,6 +143,7 @@ function StepContainer(props: StepContainerProps) {
{props.historyNode.step.name === "Waiting for user input" && (
<input
+ ref={userInputRef}
className="m-auto p-2 rounded-md border-1 border-solid text-white w-3/4 border-gray-200 bg-vsc-background"
onKeyDown={(e) => {
if (e.key === "Enter") {