diff options
7 files changed, 108 insertions, 24 deletions
diff --git a/continuedev/src/continuedev/core/policy.py b/continuedev/src/continuedev/core/policy.py index 4287bb6e..e65b6c9d 100644 --- a/continuedev/src/continuedev/core/policy.py +++ b/continuedev/src/continuedev/core/policy.py @@ -17,7 +17,10 @@ class DemoPolicy(Policy): def next(self, history: History) -> Step: # At the very start, run initial Steps spcecified in the config if history.get_current() is None: - return MessageStep(message="Welcome to Continue!") >> SetupContinueWorkspaceStep() >> CreateCodebaseIndexChroma() >> StepsOnStartupStep() + return (MessageStep(message="Welcome to Continue!") >> + SetupContinueWorkspaceStep() >> + CreateCodebaseIndexChroma() >> + StepsOnStartupStep()) observation = history.get_current().observation if observation is not None and isinstance(observation, UserInputObservation): diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py index 4a4604d6..55c25da4 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py @@ -11,7 +11,7 @@ class CreatePipelineRecipe(Step): hide: bool = True async def run(self, sdk: ContinueSDK): - await sdk.run_step( + text_observation = await sdk.run_step( MessageStep(message=dedent("""\ This recipe will walk you through the process of creating a dlt pipeline for your chosen data source. With the help of Continue, you will: - Create a Python virtual environment with dlt installed @@ -21,7 +21,10 @@ class CreatePipelineRecipe(Step): - Test that the API call works - Load the data into a local DuckDB instance - Write a query to view the data""")) >> - WaitForUserInputStep(prompt="What API do you want to load data from?") >> - SetupPipelineStep(api_description="WeatherAPI.com API") >> + WaitForUserInputStep( + prompt="What API do you want to load data from?") + ) + await sdk.run_step( + SetupPipelineStep(api_description=text_observation.text) >> ValidatePipelineStep() ) diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index fdcd9837..ad468595 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -191,13 +191,18 @@ class WaitForUserInputStep(Step): name: str = "Waiting for user input" _description: Union[str, None] = None + _response: Union[str, None] = None async def describe(self, models: Models) -> Coroutine[str, None, None]: - return self.prompt + if self._response is None: + return self.prompt + else: + return self.prompt + "\n\n" + self._response async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: self._description = self.prompt resp = await sdk.wait_for_user_input() + self._response = resp return TextObservation(text=resp) diff --git a/extension/react-app/src/components/ContinueButton.tsx b/extension/react-app/src/components/ContinueButton.tsx index 11dc7a92..c6117bf9 100644 --- a/extension/react-app/src/components/ContinueButton.tsx +++ b/extension/react-app/src/components/ContinueButton.tsx @@ -24,9 +24,13 @@ let StyledButton = styled(Button)` } `; -function ContinueButton(props: { onClick?: () => void }) { +function ContinueButton(props: { onClick?: () => void; hidden?: boolean }) { return ( - <StyledButton className="m-auto" onClick={props.onClick}> + <StyledButton + hidden={props.hidden} + className="m-auto" + onClick={props.onClick} + > <Play /> {/* <img src={"/continue_arrow.png"} width="16px"></img> */} Continue diff --git a/extension/react-app/src/components/InputAndButton.tsx b/extension/react-app/src/components/InputAndButton.tsx new file mode 100644 index 00000000..0a8592f2 --- /dev/null +++ b/extension/react-app/src/components/InputAndButton.tsx @@ -0,0 +1,77 @@ +import React, { useRef } from "react"; +import styled from "styled-components"; +import { vscBackground } from "."; + +interface InputAndButtonProps { + onUserInput: (input: string) => void; +} + +const TopDiv = styled.div` + display: grid; + grid-template-columns: 3fr 1fr; + grid-gap: 0; +`; + +const Input = styled.input` + padding: 0.5rem; + border: 1px solid white; + background-color: ${vscBackground}; + color: white; + border-radius: 4px; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + outline: none; +`; + +const Button = styled.button` + padding: 0.5rem; + border: 1px solid white; + background-color: ${vscBackground}; + color: white; + border-radius: 4px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left: 0; + cursor: pointer; + + &:hover { + background-color: white; + color: black; + } +`; + +function InputAndButton(props: InputAndButtonProps) { + const userInputRef = useRef<HTMLInputElement>(null); + + return ( + <TopDiv className="grid grid-cols-2 space-x-0"> + <Input + ref={userInputRef} + onKeyDown={(e) => { + if (e.key === "Enter") { + props.onUserInput(e.currentTarget.value); + } + }} + type="text" + onSubmit={(ev) => { + props.onUserInput(ev.currentTarget.value); + }} + onClick={(e) => { + e.stopPropagation(); + }} + /> + <Button + onClick={(e) => { + if (userInputRef.current) { + props.onUserInput(userInputRef.current.value); + } + e.stopPropagation(); + }} + > + Enter + </Button> + </TopDiv> + ); +} + +export default InputAndButton; diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index 903f9b94..f54d4d75 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -23,6 +23,7 @@ import { import { HistoryNode } from "../../../schema/HistoryNode"; import ReactMarkdown from "react-markdown"; import ContinueButton from "./ContinueButton"; +import InputAndButton from "./InputAndButton"; interface StepContainerProps { historyNode: HistoryNode; @@ -177,22 +178,11 @@ 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") { - props.onUserInput(e.currentTarget.value); - } + <InputAndButton + onUserInput={(value) => { + props.onUserInput(value); }} - type="text" - onSubmit={(ev) => { - props.onUserInput(ev.currentTarget.value); - }} - onClick={(e) => { - e.stopPropagation(); - }} - /> + ></InputAndButton> )} {props.historyNode.step.name === "Waiting for user confirmation" && ( <> diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index a08698a4..7dd30acb 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -38,11 +38,11 @@ function GUI(props: GUIProps) { const [waitingForSteps, setWaitingForSteps] = useState(false); const [userInputQueue, setUserInputQueue] = useState<string[]>([]); const [history, setHistory] = useState<History | undefined>(); - // { + // { // timeline: [ // { // step: { - // name: "RunCodeStep", + // name: "Waiting for user input", // cmd: "python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py", // description: // "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py`", @@ -189,6 +189,8 @@ function GUI(props: GUIProps) { if (mainTextInputRef.current) { if (!client) return; let input = mainTextInputRef.current.value; + if (input.trim() === "") return; + setWaitingForSteps(true); client.sendMainInput(input); setUserInputQueue((queue) => { |