From d27c95686efb52182ce8cb24f48d197ba42510ab Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Wed, 12 Jul 2023 13:22:40 -0700 Subject: purging unecessary files --- extension/react-app/src/pages/gui.tsx | 486 ++++++++++++++++++++++++++++++++++ 1 file changed, 486 insertions(+) create mode 100644 extension/react-app/src/pages/gui.tsx (limited to 'extension/react-app/src/pages') diff --git a/extension/react-app/src/pages/gui.tsx b/extension/react-app/src/pages/gui.tsx new file mode 100644 index 00000000..b6a18dc8 --- /dev/null +++ b/extension/react-app/src/pages/gui.tsx @@ -0,0 +1,486 @@ +import styled from "styled-components"; +import { defaultBorderRadius } from "../components"; +import Loader from "../components/Loader"; +import ContinueButton from "../components/ContinueButton"; +import { FullState, HighlightedRangeContext } from "../../../schema/FullState"; +import { useCallback, useEffect, useRef, useState, useContext } from "react"; +import { History } from "../../../schema/History"; +import { HistoryNode } from "../../../schema/HistoryNode"; +import StepContainer from "../components/StepContainer"; +import { GUIClientContext } from "../App"; +import { + BookOpen, + ChatBubbleOvalLeftEllipsis, + Trash, +} from "@styled-icons/heroicons-outline"; +import ComboBox from "../components/ComboBox"; +import TextDialog from "../components/TextDialog"; +import HeaderButtonWithText from "../components/HeaderButtonWithText"; +import ReactSwitch from "react-switch"; +import { usePostHog } from "posthog-js/react"; +import { useSelector } from "react-redux"; +import { RootStore } from "../redux/store"; +import LoadingCover from "../components/LoadingCover"; +import { postVscMessage } from "../vscode"; +import UserInputContainer from "../components/UserInputContainer"; +import Onboarding from "../components/Onboarding"; + +const TopGUIDiv = styled.div` + overflow: hidden; +`; + +const UserInputQueueItem = styled.div` + border-radius: ${defaultBorderRadius}; + color: gray; + padding: 8px; + margin: 8px; + text-align: center; +`; + +const Footer = styled.footer<{ dataSwitchChecked: boolean }>` + display: flex; + flex-direction: row; + gap: 8px; + justify-content: right; + padding: 8px; + align-items: center; + margin-top: 8px; + border-top: 0.1px solid gray; + background-color: ${(props) => + props.dataSwitchChecked ? "#12887a33" : "transparent"}; +`; + +interface GUIProps { + firstObservation?: any; +} + +function GUI(props: GUIProps) { + const client = useContext(GUIClientContext); + const posthog = usePostHog(); + const vscMachineId = useSelector( + (state: RootStore) => state.config.vscMachineId + ); + const [dataSwitchChecked, setDataSwitchChecked] = useState(false); + const dataSwitchOn = useSelector( + (state: RootStore) => state.config.dataSwitchOn + ); + + useEffect(() => { + if (typeof dataSwitchOn !== "undefined") { + setDataSwitchChecked(dataSwitchOn); + } + }, [dataSwitchOn]); + + const [usingFastModel, setUsingFastModel] = useState(false); + const [waitingForSteps, setWaitingForSteps] = useState(false); + const [userInputQueue, setUserInputQueue] = useState([]); + const [highlightedRanges, setHighlightedRanges] = useState< + HighlightedRangeContext[] + >([]); + const [addingHighlightedCode, setAddingHighlightedCode] = useState(false); + const [availableSlashCommands, setAvailableSlashCommands] = useState< + { name: string; description: string }[] + >([]); + const [pinned, setPinned] = useState(false); + const [showDataSharingInfo, setShowDataSharingInfo] = useState(false); + const [stepsOpen, setStepsOpen] = useState([ + true, + true, + true, + true, + ]); + const [history, setHistory] = useState({ + timeline: [ + { + step: { + name: "Welcome to Continue", + hide: false, + 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: "", + }, + depth: 0, + deleted: false, + active: false, + }, + ], + current_index: 3, + } as any); + + const [showFeedbackDialog, setShowFeedbackDialog] = useState(false); + const [feedbackDialogMessage, setFeedbackDialogMessage] = useState(""); + + const topGuiDivRef = useRef(null); + + const [scrollTimeout, setScrollTimeout] = useState( + null + ); + const scrollToBottom = useCallback(() => { + if (scrollTimeout) { + clearTimeout(scrollTimeout); + } + // Debounced smooth scroll to bottom of screen + if (topGuiDivRef.current) { + const timeout = setTimeout(() => { + window.scrollTo({ + top: topGuiDivRef.current!.offsetHeight, + behavior: "smooth", + }); + }, 200); + setScrollTimeout(timeout); + } + }, [topGuiDivRef.current, scrollTimeout]); + + useEffect(() => { + const listener = (e: any) => { + // Cmd + i to toggle fast model + if (e.key === "i" && e.metaKey && e.shiftKey) { + setUsingFastModel((prev) => !prev); + // Cmd + backspace to stop currently running step + } else if ( + e.key === "Backspace" && + e.metaKey && + typeof history?.current_index !== "undefined" && + history.timeline[history.current_index]?.active + ) { + client?.deleteAtIndex(history.current_index); + } + }; + window.addEventListener("keydown", listener); + + return () => { + window.removeEventListener("keydown", listener); + }; + }, [client, history]); + + useEffect(() => { + client?.onStateUpdate((state: FullState) => { + // Scroll only if user is at very bottom of the window. + setUsingFastModel(state.default_model === "gpt-3.5-turbo"); + const shouldScrollToBottom = + topGuiDivRef.current && + topGuiDivRef.current?.offsetHeight - window.scrollY < 100; + + const waitingForSteps = + state.active && + state.history.current_index < state.history.timeline.length && + state.history.timeline[state.history.current_index] && + state.history.timeline[ + state.history.current_index + ].step.description?.trim() === ""; + + setWaitingForSteps(waitingForSteps); + setHistory(state.history); + setHighlightedRanges(state.highlighted_ranges); + setUserInputQueue(state.user_input_queue); + setAddingHighlightedCode(state.adding_highlighted_code); + setAvailableSlashCommands( + state.slash_commands.map((c: any) => { + return { + name: `/${c.name}`, + description: c.description, + }; + }) + ); + setStepsOpen((prev) => { + const nextStepsOpen = [...prev]; + for ( + let i = nextStepsOpen.length; + i < state.history.timeline.length; + i++ + ) { + nextStepsOpen.push(true); + } + return nextStepsOpen; + }); + + if (shouldScrollToBottom) { + scrollToBottom(); + } + }); + }, [client]); + + useEffect(() => { + scrollToBottom(); + }, [waitingForSteps]); + + const mainTextInputRef = useRef(null); + + const deleteContextItems = useCallback( + (indices: number[]) => { + client?.deleteContextAtIndices(indices); + }, + [client] + ); + + const onMainTextInput = (event?: any) => { + if (mainTextInputRef.current) { + let input = (mainTextInputRef.current as any).inputValue; + // cmd+enter to /edit + if (event?.metaKey) { + input = `/edit ${input}`; + } + (mainTextInputRef.current as any).setInputValue(""); + if (!client) return; + + setWaitingForSteps(true); + + if ( + history && + history.current_index >= 0 && + history.current_index < history.timeline.length + ) { + if ( + history.timeline[history.current_index]?.step.name === + "Waiting for user input" + ) { + if (input.trim() === "") return; + onStepUserInput(input, history!.current_index); + return; + } else if ( + history.timeline[history.current_index]?.step.name === + "Waiting for user confirmation" + ) { + onStepUserInput("ok", history!.current_index); + return; + } + } + if (input.trim() === "") return; + + client.sendMainInput(input); + setUserInputQueue((queue) => { + return [...queue, input]; + }); + } + }; + + const onStepUserInput = (input: string, index: number) => { + if (!client) return; + console.log("Sending step user input", input, index); + client.sendStepUserInput(input, index); + }; + + // const iterations = useSelector(selectIterations); + return ( + <> + +