From 2ec0b4118bd092a528a1171df6ae4ffcd7cfb33b Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 4 Jul 2023 12:47:28 -0700 Subject: better control over context --- extension/react-app/src/components/ComboBox.tsx | 57 +++++++++++++++++++--- .../src/components/HeaderButtonWithText.tsx | 2 + extension/react-app/src/components/PillButton.tsx | 9 ++-- extension/react-app/src/components/index.ts | 13 +++-- 4 files changed, 64 insertions(+), 17 deletions(-) (limited to 'extension/react-app/src/components') diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index 742c643b..bdb8850d 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import { useCombobox } from "downshift"; import styled from "styled-components"; import { @@ -10,7 +10,10 @@ import { import CodeBlock from "./CodeBlock"; import { RangeInFile } from "../../../src/client"; import PillButton from "./PillButton"; +import HeaderButtonWithText from "./HeaderButtonWithText"; +import { Trash, LockClosed, LockOpen } from "@styled-icons/heroicons-outline"; +// #region styled components const mainInputFontSize = 16; const ContextDropdown = styled.div` @@ -87,13 +90,16 @@ const Li = styled.li<{ cursor: pointer; `; +// #endregion + interface ComboBoxProps { items: { name: string; description: string }[]; onInputValueChange: (inputValue: string) => void; disabled?: boolean; - onEnter?: (e: React.KeyboardEvent) => void; - highlightedCodeSections?: (RangeInFile & { contents: string })[]; - deleteContextItem?: (idx: number) => void; + onEnter: (e: React.KeyboardEvent) => void; + highlightedCodeSections: (RangeInFile & { contents: string })[]; + deleteContextItems: (indices: number[]) => void; + onTogglePin: () => void; } const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { @@ -104,6 +110,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { const [hoveringButton, setHoveringButton] = React.useState(false); const [hoveringContextDropdown, setHoveringContextDropdown] = React.useState(false); + const [pinned, setPinned] = useState(false); const [highlightedCodeSections, setHighlightedCodeSections] = React.useState( props.highlightedCodeSections || [ { @@ -242,12 +249,46 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
+ {highlightedCodeSections.length > 0 && ( + <> + { + props.deleteContextItems( + highlightedCodeSections.map((_, idx) => idx) + ); + }} + > + + + { + setPinned((prev) => !prev); + props.onTogglePin(); + }} + > + {pinned ? ( + + ) : ( + + )} + + + )} {highlightedCodeSections.map((section, idx) => ( { - if (props.deleteContextItem) { - props.deleteContextItem(idx); + if (props.deleteContextItems) { + props.deleteContextItems([idx]); } setHighlightedCodeSections((prev) => { const newSections = [...prev]; @@ -280,7 +321,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { onMouseLeave={() => { setHoveringContextDropdown(false); }} - hidden={!hoveringContextDropdown && !hoveringButton} + hidden={true || (!hoveringContextDropdown && !hoveringButton)} > {highlightedCodeSections.map((section, idx) => ( <> diff --git a/extension/react-app/src/components/HeaderButtonWithText.tsx b/extension/react-app/src/components/HeaderButtonWithText.tsx index 30931f86..3ddac93c 100644 --- a/extension/react-app/src/components/HeaderButtonWithText.tsx +++ b/extension/react-app/src/components/HeaderButtonWithText.tsx @@ -7,12 +7,14 @@ interface HeaderButtonWithTextProps { onClick?: (e: any) => void; children: React.ReactNode; disabled?: boolean; + inverted?: boolean; } const HeaderButtonWithText = (props: HeaderButtonWithTextProps) => { const [hover, setHover] = useState(false); return ( { diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx index 33451db5..55fe1ac6 100644 --- a/extension/react-app/src/components/PillButton.tsx +++ b/extension/react-app/src/components/PillButton.tsx @@ -1,6 +1,7 @@ import { useState } from "react"; import styled from "styled-components"; import { defaultBorderRadius } from "."; +import { XMark } from "@styled-icons/heroicons-outline"; const Button = styled.button` border: none; @@ -42,13 +43,12 @@ const PillButton = (props: PillButtonProps) => {
- {props.title} + {props.title}
); diff --git a/extension/react-app/src/components/index.ts b/extension/react-app/src/components/index.ts index 429a7df5..db1925ed 100644 --- a/extension/react-app/src/components/index.ts +++ b/extension/react-app/src/components/index.ts @@ -124,16 +124,19 @@ export const appear = keyframes` } `; -export const HeaderButton = styled.button` - background-color: transparent; +export const HeaderButton = styled.button<{ inverted: boolean | undefined }>` + background-color: ${({ inverted }) => (inverted ? "white" : "transparent")}; + color: ${({ inverted }) => (inverted ? "black" : "white")}; + border: 1px solid white; border-radius: ${defaultBorderRadius}; cursor: pointer; - color: white; &:hover { - background-color: white; - color: black; + background-color: ${({ inverted }) => + typeof inverted === "undefined" || inverted ? "white" : "transparent"}; + color: ${({ inverted }) => + typeof inverted === "undefined" || inverted ? "black" : "white"}; } display: flex; align-items: center; -- cgit v1.2.3-70-g09d2 From 4b1d10f3bae1f1c80ecf74993f18f318c7b22b7f Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 4 Jul 2023 13:43:09 -0700 Subject: many fixes --- continuedev/src/continuedev/core/autopilot.py | 11 ++++++++--- continuedev/src/continuedev/core/main.py | 7 +++---- continuedev/src/continuedev/core/sdk.py | 13 ++++++++++++- continuedev/src/continuedev/steps/chat.py | 1 + extension/package-lock.json | 4 ++-- extension/package.json | 4 ++-- extension/react-app/src/components/ComboBox.tsx | 10 +++------- extension/react-app/src/components/PillButton.tsx | 1 - extension/react-app/src/components/UserInputContainer.tsx | 6 ++++-- extension/react-app/src/tabs/gui.tsx | 5 ++--- 10 files changed, 37 insertions(+), 25 deletions(-) (limited to 'extension/react-app/src/components') diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index 05e48f40..313ceded 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -144,9 +144,7 @@ class Autopilot(ContinueBaseModel): async def handle_highlighted_code(self, range_in_files: List[RangeInFileWithContents]): workspace_path = self.continue_sdk.ide.workspace_directory for rif in range_in_files: - rif.filepath = os.path.relpath(rif.filepath, workspace_path) - if rif.filepath.startswith(".."): - rif.filepath = os.path.basename(rif.filepath) + rif.filepath = os.path.basename(rif.filepath) # If current range overlaps with any others, delete them and only keep the new range new_ranges = [] @@ -156,6 +154,13 @@ class Autopilot(ContinueBaseModel): if rif.filepath == new_rif.filepath and rif.range.overlaps_with(new_rif.range): found_overlap = True break + + # Also don't allow multiple ranges in same file with same content. This is useless to the model, and avoids + # the bug where cmd+f causes repeated highlights + if rif.filepath == new_rif.filepath and rif.contents == new_rif.contents: + found_overlap = True + break + if not found_overlap: new_ranges.append(rif) diff --git a/continuedev/src/continuedev/core/main.py b/continuedev/src/continuedev/core/main.py index 9a6617f4..8bad09d1 100644 --- a/continuedev/src/continuedev/core/main.py +++ b/continuedev/src/continuedev/core/main.py @@ -107,11 +107,9 @@ class HistoryNode(ContinueBaseModel): return self.step.chat_context return self.step.chat_context + [ ChatMessage( - role="function", + role="assistant", name=self.step.__class__.__name__, - content=json.dumps({ - "description": self.step.description or "Function complete", - }), + content=self.step.description or f"Ran function {self.step.name}", summary=f"Called function {self.step.name}" )] @@ -200,6 +198,7 @@ class SlashCommandDescription(ContinueBaseModel): name: str description: str + class FullState(ContinueBaseModel): """A full state of the program, including the history""" history: History diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py index 988ac6b0..fe975b99 100644 --- a/continuedev/src/continuedev/core/sdk.py +++ b/continuedev/src/continuedev/core/sdk.py @@ -97,7 +97,18 @@ class ContinueSDK(AbstractContinueSDK): async def _ensure_absolute_path(self, path: str) -> str: if os.path.isabs(path): return path - return os.path.join(self.ide.workspace_directory, path) + + # Else if in workspace + workspace_path = os.path.join(self.ide.workspace_directory, path) + if os.path.exists(workspace_path): + return workspace_path + else: + # Check if it matches any of the open files, then use that absolute path + open_files = await self.ide.getOpenFiles() + for open_file in open_files: + if os.path.basename(open_file) == os.path.basename(path): + return open_file + raise Exception(f"Path {path} does not exist") async def run_step(self, step: Step) -> Coroutine[Observation, None, None]: return await self.__autopilot._run_singular_step(step) diff --git a/continuedev/src/continuedev/steps/chat.py b/continuedev/src/continuedev/steps/chat.py index 49dd98e4..db3f9d7f 100644 --- a/continuedev/src/continuedev/steps/chat.py +++ b/continuedev/src/continuedev/steps/chat.py @@ -149,6 +149,7 @@ class ChatWithFunctions(Step): name: str = "Input" manage_own_chat_context: bool = True description: str = "" + hide: bool = True async def run(self, sdk: ContinueSDK): await sdk.update_ui() diff --git a/extension/package-lock.json b/extension/package-lock.json index c9b8b757..94823004 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.0.106", + "version": "0.0.107", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "continue", - "version": "0.0.106", + "version": "0.0.107", "license": "Apache-2.0", "dependencies": { "@electron/rebuild": "^3.2.10", diff --git a/extension/package.json b/extension/package.json index 184d16e2..6434efc3 100644 --- a/extension/package.json +++ b/extension/package.json @@ -14,7 +14,7 @@ "displayName": "Continue", "pricing": "Free", "description": "The open-source coding autopilot", - "version": "0.0.106", + "version": "0.0.107", "publisher": "Continue", "engines": { "vscode": "^1.67.0" @@ -55,7 +55,7 @@ }, "continue.OPENAI_API_KEY": { "type": "password", - "default": "", + "default": null, "description": "The OpenAI API key to use for code generation." }, "continue.dataSwitch": { diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index bdb8850d..3e1f3e16 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -279,13 +279,9 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { )} {highlightedCodeSections.map((section, idx) => ( { if (props.deleteContextItems) { props.deleteContextItems([idx]); diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx index 55fe1ac6..2352c3ad 100644 --- a/extension/react-app/src/components/PillButton.tsx +++ b/extension/react-app/src/components/PillButton.tsx @@ -50,7 +50,6 @@ const PillButton = (props: PillButtonProps) => { borderRight: "1px solid black", paddingRight: "4px", }} - hidden={!isHovered} onClick={() => { props.onDelete?.(); props.onHover?.(false); diff --git a/extension/react-app/src/components/UserInputContainer.tsx b/extension/react-app/src/components/UserInputContainer.tsx index 59453169..44fdba38 100644 --- a/extension/react-app/src/components/UserInputContainer.tsx +++ b/extension/react-app/src/components/UserInputContainer.tsx @@ -6,10 +6,12 @@ import HeaderButtonWithText from "./HeaderButtonWithText"; import { Play, XMark } from "@styled-icons/heroicons-outline"; import { RootStore } from "../redux/store"; import { useSelector } from "react-redux"; +import { HistoryNode } from "../../../schema/HistoryNode"; interface UserInputContainerProps { onDelete: () => void; children: string; + historyNode: HistoryNode; } const StyledDiv = styled.div` @@ -26,7 +28,7 @@ const StyledDiv = styled.div` const UserInputContainer = (props: UserInputContainerProps) => { return ( - + diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index c2ff101a..8bfadc05 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -70,9 +70,7 @@ function GUI(props: GUIProps) { const [usingFastModel, setUsingFastModel] = useState(false); const [waitingForSteps, setWaitingForSteps] = useState(false); const [userInputQueue, setUserInputQueue] = useState([]); - const [highlightedRanges, setHighlightedRanges] = useState([ - { filepath: "abc.txt", range: { start: { line: 2 }, end: { line: 4 } } }, - ]); + const [highlightedRanges, setHighlightedRanges] = useState([]); const [availableSlashCommands, setAvailableSlashCommands] = useState< { name: string; description: string }[] >([]); @@ -296,6 +294,7 @@ function GUI(props: GUIProps) { onDelete={() => { client?.deleteAtIndex(index); }} + historyNode={node} > {node.step.description as string} -- cgit v1.2.3-70-g09d2 From 2d8c28965684d03ef711253e5555ef304882828f Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 4 Jul 2023 14:01:59 -0700 Subject: details --- extension/react-app/src/components/StepContainer.tsx | 3 ++- extension/react-app/src/tabs/gui.tsx | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'extension/react-app/src/components') diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index ab0d307f..35d34976 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -81,7 +81,8 @@ const MarkdownPre = styled.pre` const StyledCode = styled.code` word-wrap: break-word; - color: lightgray; + color: #f69292; + background: transparent; `; const gradient = keyframes` diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 8bfadc05..bbf0b126 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -88,13 +88,16 @@ function GUI(props: GUIProps) { step: { name: "Welcome to Continue", hide: false, - description: - "Highlight code and ask a question or give instructions. Past steps are used as additional context by default. Use slash commands when you want fine-grained control.", + description: `- Highlight code and ask a question or give instructions +- Use \`cmd+k\` (Mac) / \`ctrl+k\` (Windows) to open Continue +- Use \`cmd+shift+e\` / \`ctrl+shift+e\` to open file Explorer +- Add your own OpenAI API key to VS Code Settings with \`cmd+,\` +- Use slash commands when you want fine-grained control +- Past steps are included as part of the context by default`, system_message: null, chat_context: [], manage_own_chat_context: false, - message: - "Highlight code and ask a question or give instructions. Past steps are used as additional context by default. Use slash commands when you want fine-grained control.", + message: "", }, depth: 0, deleted: false, -- cgit v1.2.3-70-g09d2