From 0da3647105a8098f9218e0d6c8105b9d60c1cb28 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Thu, 15 Jun 2023 18:15:11 -0700 Subject: footer sticks to bottom --- extension/react-app/src/tabs/gui.tsx | 201 +++++++++++++++++------------------ 1 file changed, 96 insertions(+), 105 deletions(-) (limited to 'extension/react-app/src/tabs') diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 5316f42b..05795cdf 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -21,18 +21,11 @@ import { import ComboBox from "../components/ComboBox"; import TextDialog from "../components/TextDialog"; -const MainDiv = styled.div` - display: grid; - grid-template-rows: 1fr auto; +const TopGUIDiv = styled.div` + overflow: hidden; `; -let TopGUIDiv = styled.div` - display: grid; - grid-template-columns: 1fr; - background-color: ${vscBackground}; -`; - -let UserInputQueueItem = styled.div` +const UserInputQueueItem = styled.div` border-radius: ${defaultBorderRadius}; color: gray; padding: 8px; @@ -40,7 +33,7 @@ let UserInputQueueItem = styled.div` text-align: center; `; -const TopBar = styled.div` +const Footer = styled.footer` display: flex; flex-direction: row; gap: 8px; @@ -303,103 +296,101 @@ function GUI(props: GUIProps) { setShowFeedbackDialog(false); }} > - - { - if (e.key === "Enter" && e.ctrlKey) { - onMainTextInput(); - } - }} - > - {typeof client === "undefined" && ( - <> - -

- Trying to reconnect with server... -

- - )} - {history?.timeline.map((node: HistoryNode, index: number) => { - return ( - { - onStepUserInput(input, index); - }} - inFuture={index > history?.current_index} - historyNode={node} - onRefinement={(input: string) => { - client?.sendRefinementInput(input, index); - }} - onReverse={() => { - client?.reverseToIndex(index); - }} - onRetry={() => { - client?.retryAtIndex(index); - setWaitingForSteps(true); - }} - onDelete={() => { - client?.deleteAtIndex(index); - }} - /> - ); - })} - {waitingForSteps && } -
- {userInputQueue.map((input) => { - return {input}; - })} -
- - { - onMainTextInput(); - e.stopPropagation(); - e.preventDefault(); - }} - onInputValueChange={() => {}} - items={availableSlashCommands} - /> - - - - - - Continue Docs - - - - { - // Set dialog open - setShowFeedbackDialog(true); + { + if (e.key === "Enter" && e.ctrlKey) { + onMainTextInput(); + } + }} + > + {typeof client === "undefined" && ( + <> + +

+ Trying to reconnect with server... +

+ + )} + {history?.timeline.map((node: HistoryNode, index: number) => { + return ( + { + onStepUserInput(input, index); + }} + inFuture={index > history?.current_index} + historyNode={node} + onRefinement={(input: string) => { + client?.sendRefinementInput(input, index); + }} + onReverse={() => { + client?.reverseToIndex(index); }} - > - Feedback - -
- { - client?.sendClear(); + onRetry={() => { + client?.retryAtIndex(index); + setWaitingForSteps(true); }} - style={{ padding: "3px" }} - > - Clear History - - -
-
-
+ onDelete={() => { + client?.deleteAtIndex(index); + }} + /> + ); + })} + {waitingForSteps && } + +
+ {userInputQueue.map((input) => { + return {input}; + })} +
+ + { + onMainTextInput(); + e.stopPropagation(); + e.preventDefault(); + }} + onInputValueChange={() => {}} + items={availableSlashCommands} + /> + + +
+ + + Continue Docs + + + + { + // Set dialog open + setShowFeedbackDialog(true); + }} + > + Feedback + + + { + client?.sendClear(); + }} + style={{ padding: "3px" }} + > + Clear History + + +
); } -- cgit v1.2.3-70-g09d2 From a328d3671529935929ade8c0ca28ccb465699f8e Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Thu, 15 Jun 2023 18:22:35 -0700 Subject: hover icons for description --- .../src/components/HeaderButtonWithText.tsx | 26 ++++++++++++++++++++++ .../react-app/src/components/StepContainer.tsx | 14 ++++++------ extension/react-app/src/tabs/gui.tsx | 21 ++++++++--------- 3 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 extension/react-app/src/components/HeaderButtonWithText.tsx (limited to 'extension/react-app/src/tabs') diff --git a/extension/react-app/src/components/HeaderButtonWithText.tsx b/extension/react-app/src/components/HeaderButtonWithText.tsx new file mode 100644 index 00000000..d70a3d70 --- /dev/null +++ b/extension/react-app/src/components/HeaderButtonWithText.tsx @@ -0,0 +1,26 @@ +import React, { useState } from "react"; + +import { HeaderButton } from "."; + +interface HeaderButtonWithTextProps { + text: string; + onClick?: (e: any) => void; + children: React.ReactNode; +} + +const HeaderButtonWithText = (props: HeaderButtonWithTextProps) => { + const [hover, setHover] = useState(false); + return ( + setHover(true)} + onMouseLeave={() => setHover(false)} + onClick={props.onClick} + > + + {props.children} + + ); +}; + +export default HeaderButtonWithText; diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index b0116e92..480f517f 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -21,9 +21,7 @@ import { } from "@styled-icons/heroicons-outline"; import { HistoryNode } from "../../../schema/HistoryNode"; import ReactMarkdown from "react-markdown"; -import ContinueButton from "./ContinueButton"; -import InputAndButton from "./InputAndButton"; -import ToggleErrorDiv from "./ToggleErrorDiv"; +import HeaderButtonWithText from "./HeaderButtonWithText"; interface StepContainerProps { historyNode: HistoryNode; @@ -152,23 +150,25 @@ function StepContainer(props: StepContainerProps) { */} <> - { e.stopPropagation(); props.onDelete(); }} + text="Delete" > - + {props.historyNode.observation?.error ? ( - { e.stopPropagation(); props.onRetry(); }} > - + ) : ( <> )} diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 05795cdf..279d052b 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -14,12 +14,12 @@ import StepContainer from "../components/StepContainer"; import useContinueGUIProtocol from "../hooks/useWebsocket"; import { BookOpen, - ChatBubbleOvalLeft, ChatBubbleOvalLeftEllipsis, Trash, } from "@styled-icons/heroicons-outline"; import ComboBox from "../components/ComboBox"; import TextDialog from "../components/TextDialog"; +import HeaderButtonWithText from "../components/HeaderButtonWithText"; const TopGUIDiv = styled.div` overflow: hidden; @@ -366,30 +366,27 @@ function GUI(props: GUIProps) {
- - Continue Docs + - + - { // Set dialog open setShowFeedbackDialog(true); }} + text="Feedback" > - Feedback - - + { client?.sendClear(); }} - style={{ padding: "3px" }} + text="Clear History" > - Clear History - +
); -- cgit v1.2.3-70-g09d2 From 149db209603c5de16d4135f1fdc4f19104974861 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Fri, 16 Jun 2023 11:40:36 -0700 Subject: dlt demo work --- continuedev/src/continuedev/core/autopilot.py | 4 +++ continuedev/src/continuedev/core/config.py | 1 + .../src/continuedev/libs/util/traceback_parsers.py | 13 ++++++--- .../recipes/CreatePipelineRecipe/main.py | 4 ++- .../recipes/CreatePipelineRecipe/steps.py | 4 +-- extension/react-app/src/index.css | 1 + extension/react-app/src/tabs/gui.tsx | 34 ++++++++++++---------- extension/src/activation/activate.ts | 6 ++++ extension/src/continueIdeClient.ts | 2 +- extension/src/terminal/terminalEmulator.ts | 7 +++-- 10 files changed, 49 insertions(+), 27 deletions(-) (limited to 'extension/react-app/src/tabs') diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index 782d6270..73f46a37 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -113,6 +113,10 @@ class Autopilot(ContinueBaseModel): await self.update_subscribers() async def _run_singular_step(self, step: "Step", is_future_step: bool = False) -> Coroutine[Observation, None, None]: + # Allow config to set disallowed steps + if step.__class__.__name__ in self.continue_sdk.config.disallowed_steps: + return None + # If a parent step is deleted/cancelled, don't run this step last_depth = self._step_depth i = self.history.current_index diff --git a/continuedev/src/continuedev/core/config.py b/continuedev/src/continuedev/core/config.py index d8b29f5b..8f703758 100644 --- a/continuedev/src/continuedev/core/config.py +++ b/continuedev/src/continuedev/core/config.py @@ -22,6 +22,7 @@ class ContinueConfig(BaseModel): A pydantic class for the continue config file. """ steps_on_startup: Optional[Dict[str, Dict]] = {} + disallowed_steps: Optional[List[str]] = [] server_url: Optional[str] = None allow_anonymous_telemetry: Optional[bool] = True default_model: Literal["gpt-3.5-turbo", diff --git a/continuedev/src/continuedev/libs/util/traceback_parsers.py b/continuedev/src/continuedev/libs/util/traceback_parsers.py index 1885cc79..a2e94c26 100644 --- a/continuedev/src/continuedev/libs/util/traceback_parsers.py +++ b/continuedev/src/continuedev/libs/util/traceback_parsers.py @@ -12,9 +12,14 @@ def get_python_traceback(output: str) -> str: def get_javascript_traceback(output: str) -> str: lines = output.splitlines() - if len(lines) > 0: - first_line = lines[0].split(": ") - if len(lines) > 1 and len(first_line) > 0 and len(first_line[0]) > 0 and "at" in lines[1].lstrip(): - return output + first_line = None + for i in range(len(lines) - 1): + segs = lines[i].split(":") + if len(segs) > 1 and segs[0] != "" and segs[1].startswith(" ") and lines[i + 1].strip().startswith("at"): + first_line = lines[i] + break + + if first_line is not None: + return "\n".join(lines[lines.index(first_line):]) else: return None diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py index 92bddc98..55ef107b 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/main.py @@ -27,5 +27,7 @@ class CreatePipelineRecipe(Step): await sdk.run_step( SetupPipelineStep(api_description=text_observation.text) >> ValidatePipelineStep() >> - RunQueryStep() + RunQueryStep() >> + MessageStep( + name="Congrats!", message="You've successfully created your first dlt pipeline! 🎉") ) diff --git a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py index 1a756a76..91515dc2 100644 --- a/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py +++ b/continuedev/src/continuedev/recipes/CreatePipelineRecipe/steps.py @@ -64,7 +64,7 @@ class SetupPipelineStep(Step): # wait for user to put API key in secrets.toml await sdk.ide.setFileOpen(await sdk.ide.getWorkspaceDirectory() + "/.dlt/secrets.toml") - await sdk.wait_for_user_confirmation("If this service requires an API key, please add it to the `secrets.toml` file and then press `Continue`. Otherwise, type '/edit this API does not require an API key'") + await sdk.wait_for_user_confirmation("If this service requires an API key, please add it to the `secrets.toml` file and then press `Continue`.") sdk.context.set("source_name", source_name) @@ -172,5 +172,5 @@ class RunQueryStep(Step): This is a brief summary of the error followed by a suggestion on how it can be fixed:""")) sdk.raise_exception( - title="Error while running query", message=output, with_step=MessageStep(name=f"Suggestion to solve error {AI_ASSISTED_STRING}", message=suggestion) + title="Error while running query", message=output, with_step=MessageStep(name=f"Suggestion to solve error {AI_ASSISTED_STRING}", message=suggestion + "\n\nIt is also very likely that no duckdb table was created, which can happen if the resource function did not yield any data. Please make sure that it is yielding data and then rerun this step.") ) diff --git a/extension/react-app/src/index.css b/extension/react-app/src/index.css index 32a92d0e..db8afab9 100644 --- a/extension/react-app/src/index.css +++ b/extension/react-app/src/index.css @@ -22,6 +22,7 @@ html, body, #root { height: 100%; + background-color: var(--vsc-background); } body { diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 279d052b..994cb896 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -194,7 +194,7 @@ function GUI(props: GUIProps) { if (topGuiDivRef.current) { const timeout = setTimeout(() => { window.scrollTo({ - top: window.outerHeight, + top: topGuiDivRef.current!.offsetHeight, behavior: "smooth", }); }, 200); @@ -206,7 +206,9 @@ function GUI(props: GUIProps) { console.log("CLIENT ON STATE UPDATE: ", client, client?.onStateUpdate); client?.onStateUpdate((state) => { // Scroll only if user is at very bottom of the window. - const shouldScrollToBottom = window.outerHeight - window.scrollY < 200; + const shouldScrollToBottom = + topGuiDivRef.current && + topGuiDivRef.current?.offsetHeight - window.scrollY < 100; setWaitingForSteps(state.active); setHistory(state.history); setUserInputQueue(state.user_input_queue); @@ -347,12 +349,12 @@ function GUI(props: GUIProps) { { onMainTextInput(); @@ -365,6 +367,14 @@ function GUI(props: GUIProps) { ); diff --git a/extension/src/activation/activate.ts b/extension/src/activation/activate.ts index 77010241..32726c86 100644 --- a/extension/src/activation/activate.ts +++ b/extension/src/activation/activate.ts @@ -59,6 +59,9 @@ export function activateExtension( name: "Continue", }); terminal.dispose(); + if (!ideProtocolClient.continueTerminal) { + ideProtocolClient.continueTerminal = capturedTerminal; + } }); // If any terminals are open to start, replace them @@ -77,6 +80,9 @@ export function activateExtension( } ); terminal.dispose(); + if (!ideProtocolClient.continueTerminal) { + ideProtocolClient.continueTerminal = capturedTerminal; + } }); extensionContext = context; diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index a889d3dc..9a93a4ef 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -323,7 +323,7 @@ class IdeProtocolClient { return rangeInFiles; } - private continueTerminal: CapturedTerminal | undefined; + public continueTerminal: CapturedTerminal | undefined; async runCommand(command: string) { if (!this.continueTerminal || this.continueTerminal.isClosed()) { diff --git a/extension/src/terminal/terminalEmulator.ts b/extension/src/terminal/terminalEmulator.ts index 9d90b331..ff2060f8 100644 --- a/extension/src/terminal/terminalEmulator.ts +++ b/extension/src/terminal/terminalEmulator.ts @@ -76,7 +76,8 @@ export class CapturedTerminal { (lines.length > 0 && (last_line.includes("bash-") || last_line.includes(") $ ")) && last_line.includes("$")) || - (last_line.includes("]> ") && last_line.includes(") [")) + (last_line.includes("]> ") && last_line.includes(") [")) || + (last_line.includes(" (") && last_line.includes(")>")) ); } @@ -98,7 +99,7 @@ export class CapturedTerminal { if (!this.hasRunCommand) { this.hasRunCommand = true; // Let the first bash- prompt appear and let python env be opened - await this.waitForCommandToFinish(); + // await this.waitForCommandToFinish(); } if (this.commandQueue.length === 0) { @@ -154,7 +155,7 @@ export class CapturedTerminal { // Create the pseudo terminal this.ptyProcess = pty.spawn(this.shellCmd, [], { name: "xterm-256color", - cols: 160, // TODO: Get size of vscode terminal, and change with resize + cols: 250, // No way to get the size of VS Code terminal, or listen to resize, so make it just bigger than most conceivable VS Code widths rows: 26, cwd: getRootDir(), env, -- cgit v1.2.3-70-g09d2