diff options
| author | Nate Sesti <sestinj@gmail.com> | 2023-06-01 20:59:10 -0400 | 
|---|---|---|
| committer | Nate Sesti <sestinj@gmail.com> | 2023-06-01 20:59:10 -0400 | 
| commit | ef0fcedffc53b5ba455b230b112306a46ee0235f (patch) | |
| tree | f430946200daa92e00682b27526653d564a8e512 | |
| parent | 5ce90853586fcfaa7d795e2593aaaecce4bbed49 (diff) | |
| download | sncontinue-ef0fcedffc53b5ba455b230b112306a46ee0235f.tar.gz sncontinue-ef0fcedffc53b5ba455b230b112306a46ee0235f.tar.bz2 sncontinue-ef0fcedffc53b5ba455b230b112306a46ee0235f.zip | |
enter secrets directly into .env file
| -rw-r--r-- | continuedev/src/continuedev/core/env.py | 10 | ||||
| -rw-r--r-- | continuedev/src/continuedev/core/sdk.py | 37 | ||||
| -rw-r--r-- | continuedev/src/continuedev/models/filesystem_edit.py | 4 | ||||
| -rw-r--r-- | continuedev/src/continuedev/models/main.py | 8 | ||||
| -rw-r--r-- | extension/react-app/src/components/StepContainer.tsx | 8 | 
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") { | 
