diff options
Diffstat (limited to 'extension/react-app')
-rw-r--r-- | extension/react-app/src/components/CodeBlock.tsx | 73 | ||||
-rw-r--r-- | extension/react-app/src/components/ComboBox.tsx | 258 | ||||
-rw-r--r-- | extension/react-app/src/components/IterationContainer.tsx | 77 | ||||
-rw-r--r-- | extension/react-app/src/components/StepContainer.tsx | 8 | ||||
-rw-r--r-- | extension/react-app/src/hooks/ContinueGUIClientProtocol.ts | 2 | ||||
-rw-r--r-- | extension/react-app/src/hooks/useContinueGUIProtocol.ts | 4 | ||||
-rw-r--r-- | extension/react-app/src/tabs/gui.tsx | 221 |
7 files changed, 233 insertions, 410 deletions
diff --git a/extension/react-app/src/components/CodeBlock.tsx b/extension/react-app/src/components/CodeBlock.tsx index 1624b986..17f5626b 100644 --- a/extension/react-app/src/components/CodeBlock.tsx +++ b/extension/react-app/src/components/CodeBlock.tsx @@ -61,7 +61,7 @@ function CopyButton(props: { textToCopy: string; visible: boolean }) { ); } -function CodeBlock(props: { children: React.ReactNode }) { +function CodeBlock(props: { children: string; showCopy?: boolean }) { const [result, setResult] = useState<AutoHighlightResult | undefined>( undefined ); @@ -78,39 +78,36 @@ function CodeBlock(props: { children: React.ReactNode }) { setHighlightTimeout( setTimeout(() => { - const result = hljs.highlightAuto( - (props.children as any).props.children[0], - [ - "python", - "javascript", - "typescript", - "bash", - "html", - "css", - "json", - "yaml", - "markdown", - "sql", - "java", - "c", - "cpp", - "csharp", - "go", - "kotlin", - "php", - "ruby", - "rust", - "scala", - "swift", - "dart", - "haskell", - "perl", - "r", - "julia", - "objectivec", - "ocaml", - ] - ); + const result = hljs.highlightAuto(props.children, [ + "python", + "javascript", + "typescript", + "bash", + "html", + "css", + "json", + "yaml", + "markdown", + "sql", + "java", + "c", + "cpp", + "csharp", + "go", + "kotlin", + "php", + "ruby", + "rust", + "scala", + "swift", + "dart", + "haskell", + "perl", + "r", + "julia", + "objectivec", + "ocaml", + ]); setResult(result); setHighlightTimeout(undefined); }, 100) @@ -129,13 +126,11 @@ function CodeBlock(props: { children: React.ReactNode }) { > <CopyButtonDiv> <CopyButton - visible={hovered} - textToCopy={(props.children as any).props.children[0]} + visible={hovered && (props.showCopy || true)} + textToCopy={props.children} /> </CopyButtonDiv> - <StyledCode language={result?.language}> - {(props.children as any).props.children[0]} - </StyledCode> + <StyledCode language={result?.language}>{props.children}</StyledCode> </StyledPre> ); } diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index 3816cee8..34027a42 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from "react"; +import React, { useCallback, useEffect } from "react"; import { useCombobox } from "downshift"; import styled from "styled-components"; import { @@ -7,8 +7,44 @@ import { secondaryDark, vscBackground, } from "."; +import CodeBlock from "./CodeBlock"; +import { RangeInFile } from "../../../src/client"; const mainInputFontSize = 16; + +const ContextDropdown = styled.div` + position: absolute; + padding: 4px; + width: calc(100% - 16px - 8px); + background-color: ${secondaryDark}; + color: white; + border-bottom-right-radius: ${defaultBorderRadius}; + border-bottom-left-radius: ${defaultBorderRadius}; + /* border: 1px solid white; */ + border-top: none; + margin-left: 8px; + margin-right: 8px; + margin-top: -12px; + outline: 1px solid orange; +`; + +const PillButton = styled.button` + display: flex; + justify-content: space-between; + align-items: center; + border: none; + color: white; + background-color: gray; + border-radius: 50px; + padding: 5px 10px; + margin: 5px 0; + cursor: pointer; + + &:hover { + background-color: ${buttonColor}; + } +`; + const MainTextInput = styled.textarea` resize: none; @@ -20,6 +56,7 @@ const MainTextInput = styled.textarea` width: 100%; background-color: ${vscBackground}; color: white; + z-index: 1; &:focus { border: 1px solid transparent; @@ -49,6 +86,7 @@ const Ul = styled.ul<{ border-radius: ${defaultBorderRadius}; overflow: hidden; border: 0.5px solid gray; + z-index: 2; `; const Li = styled.li<{ @@ -71,6 +109,8 @@ interface ComboBoxProps { onInputValueChange: (inputValue: string) => void; disabled?: boolean; onEnter?: (e: React.KeyboardEvent<HTMLInputElement>) => void; + highlightedCodeSections?: (RangeInFile & { contents: string })[]; + deleteContextItem?: (idx: number) => void; } const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { @@ -78,6 +118,24 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { // The position of the current command you are typing now, so the one that will be appended to history once you press enter const [positionInHistory, setPositionInHistory] = React.useState<number>(0); const [items, setItems] = React.useState(props.items); + const [showContextDropdown, setShowContextDropdown] = React.useState(false); + const [highlightedCodeSections, setHighlightedCodeSections] = React.useState( + props.highlightedCodeSections || [ + { + filepath: "test.ts", + range: { + start: { line: 0, character: 0 }, + end: { line: 0, character: 0 }, + }, + contents: "import * as a from 'a';", + }, + ] + ); + + useEffect(() => { + setHighlightedCodeSections(props.highlightedCodeSections || []); + }, [props.highlightedCodeSections]); + const { isOpen, getToggleButtonProps, @@ -111,90 +169,124 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { }; return ( - <div className="flex px-2" ref={divRef} hidden={!isOpen}> - <MainTextInput - disabled={props.disabled} - placeholder="Type '/' to see available slash commands." - {...getInputProps({ - onChange: (e) => { - const target = e.target as HTMLTextAreaElement; - // Update the height of the textarea to match the content, up to a max of 200px. - target.style.height = "auto"; - target.style.height = `${Math.min( - target.scrollHeight, - 300 - ).toString()}px`; - }, - onKeyDown: (event) => { - if (event.key === "Enter" && event.shiftKey) { - // Prevent Downshift's default 'Enter' behavior. - (event.nativeEvent as any).preventDownshiftDefault = true; - } else if ( - event.key === "Enter" && - (!isOpen || items.length === 0) - ) { - // Prevent Downshift's default 'Enter' behavior. - (event.nativeEvent as any).preventDownshiftDefault = true; - if (props.onEnter) props.onEnter(event); - setInputValue(""); - const value = event.currentTarget.value; - if (value !== "") { - setPositionInHistory(history.length + 1); - setHistory([...history, value]); + <> + <div className="flex px-2" ref={divRef} hidden={!isOpen}> + <MainTextInput + disabled={props.disabled} + placeholder="Type '/' to see available slash commands." + {...getInputProps({ + onChange: (e) => { + const target = e.target as HTMLTextAreaElement; + // Update the height of the textarea to match the content, up to a max of 200px. + target.style.height = "auto"; + target.style.height = `${Math.min( + target.scrollHeight, + 300 + ).toString()}px`; + + setShowContextDropdown(target.value.endsWith("@")); + }, + onKeyDown: (event) => { + if (event.key === "Enter" && event.shiftKey) { + // Prevent Downshift's default 'Enter' behavior. + (event.nativeEvent as any).preventDownshiftDefault = true; + } else if ( + event.key === "Enter" && + (!isOpen || items.length === 0) + ) { + // Prevent Downshift's default 'Enter' behavior. + (event.nativeEvent as any).preventDownshiftDefault = true; + if (props.onEnter) props.onEnter(event); + setInputValue(""); + const value = event.currentTarget.value; + if (value !== "") { + setPositionInHistory(history.length + 1); + setHistory([...history, value]); + } + } else if (event.key === "Tab" && items.length > 0) { + setInputValue(items[0].name); + event.preventDefault(); + } else if ( + event.key === "ArrowUp" || + (event.key === "ArrowDown" && + event.currentTarget.value.split("\n").length > 1) + ) { + (event.nativeEvent as any).preventDownshiftDefault = true; + } else if ( + event.key === "ArrowUp" && + event.currentTarget.value.split("\n").length > 1 + ) { + if (positionInHistory == 0) return; + setInputValue(history[positionInHistory - 1]); + setPositionInHistory((prev) => prev - 1); + } else if ( + event.key === "ArrowDown" && + event.currentTarget.value.split("\n").length > 1 + ) { + if (positionInHistory < history.length - 1) { + setInputValue(history[positionInHistory + 1]); + } + setPositionInHistory((prev) => + Math.min(prev + 1, history.length) + ); } - } else if (event.key === "Tab" && items.length > 0) { - setInputValue(items[0].name); - event.preventDefault(); - } else if ( - event.key === "ArrowUp" || - (event.key === "ArrowDown" && - event.currentTarget.value.split("\n").length > 1) - ) { - (event.nativeEvent as any).preventDownshiftDefault = true; - } else if ( - event.key === "ArrowUp" && - event.currentTarget.value.split("\n").length > 1 - ) { - if (positionInHistory == 0) return; - setInputValue(history[positionInHistory - 1]); - setPositionInHistory((prev) => prev - 1); - } else if ( - event.key === "ArrowDown" && - event.currentTarget.value.split("\n").length > 1 - ) { - if (positionInHistory < history.length - 1) { - setInputValue(history[positionInHistory + 1]); + }, + ref: ref as any, + })} + /> + <Ul + {...getMenuProps({ + ref: ulRef, + })} + showAbove={showAbove()} + ulHeightPixels={ulRef.current?.getBoundingClientRect().height || 0} + > + {isOpen && + items.map((item, index) => ( + <Li + key={`${item.name}${index}`} + {...getItemProps({ item, index })} + highlighted={highlightedIndex === index} + selected={selectedItem === item} + > + <span> + {item.name}: {item.description} + </span> + </Li> + ))} + </Ul> + </div> + <ContextDropdown hidden={!showContextDropdown}> + <p>Highlight code to include as context:</p> + {highlightedCodeSections.map((section, idx) => ( + <> + <p>{section.filepath}</p> + <CodeBlock showCopy={false} key={idx}> + {section.contents} + </CodeBlock> + </> + ))} + </ContextDropdown> + <div className="px-2"> + {highlightedCodeSections.map((section, idx) => ( + <PillButton + onClick={() => { + console.log("delete context item", idx); + if (props.deleteContextItem) { + props.deleteContextItem(idx); } - setPositionInHistory((prev) => - Math.min(prev + 1, history.length) - ); - } - }, - ref: ref as any, - })} - /> - <Ul - {...getMenuProps({ - ref: ulRef, - })} - showAbove={showAbove()} - ulHeightPixels={ulRef.current?.getBoundingClientRect().height || 0} - > - {isOpen && - items.map((item, index) => ( - <Li - key={`${item.name}${index}`} - {...getItemProps({ item, index })} - highlighted={highlightedIndex === index} - selected={selectedItem === item} - > - <span> - {item.name}: {item.description} - </span> - </Li> - ))} - </Ul> - </div> + setHighlightedCodeSections((prev) => { + const newSections = [...prev]; + newSections.splice(idx, 1); + return newSections; + }); + }} + > + {section.filepath} + </PillButton> + ))} + </div> + </> ); }); diff --git a/extension/react-app/src/components/IterationContainer.tsx b/extension/react-app/src/components/IterationContainer.tsx deleted file mode 100644 index a0053519..00000000 --- a/extension/react-app/src/components/IterationContainer.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { useState } from "react"; -import styled from "styled-components"; -import { - defaultBorderRadius, - MainContainerWithBorder, - secondaryDark, - vscBackground, -} from "."; -import { RangeInFile, FileEdit } from "../../../src/client"; -import CodeBlock from "./CodeBlock"; -import SubContainer from "./SubContainer"; - -import { ChevronDown, ChevronRight } from "@styled-icons/heroicons-outline"; - -export interface IterationContext { - codeSelections: RangeInFile[]; - instruction: string; - suggestedChanges: FileEdit[]; - status: "waiting" | "accepted" | "rejected"; - summary?: string; - action: string; - error?: string; -} - -interface IterationContainerProps { - iterationContext: IterationContext; -} - -const IterationContainerDiv = styled.div<{ open: boolean }>` - background-color: ${(props) => (props.open ? vscBackground : secondaryDark)}; - border-radius: ${defaultBorderRadius}; - padding: ${(props) => (props.open ? "2px" : "8px")}; -`; - -function IterationContainer(props: IterationContainerProps) { - const [open, setOpen] = useState(false); - - return ( - <MainContainerWithBorder className="m-2 overflow-hidden"> - <IterationContainerDiv open={open}> - <p - className="m-2 cursor-pointer" - onClick={() => setOpen((prev) => !prev)} - > - {open ? <ChevronDown size="1.4em" /> : <ChevronRight size="1.4em" />} - {props.iterationContext.summary || - props.iterationContext.codeSelections - .map((cs) => cs.filepath) - .join("\n")} - </p> - - {open && ( - <> - <SubContainer title="Action"> - {props.iterationContext.action} - </SubContainer> - {props.iterationContext.error && ( - <SubContainer title="Error"> - <CodeBlock>{props.iterationContext.error}</CodeBlock> - </SubContainer> - )} - {props.iterationContext.suggestedChanges.map((sc) => { - return ( - <SubContainer title="Suggested Change"> - {sc.filepath} - <CodeBlock>{sc.replacement}</CodeBlock> - </SubContainer> - ); - })} - </> - )} - </IterationContainerDiv> - </MainContainerWithBorder> - ); -} - -export default IterationContainer; diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index 02c04548..cb83f20a 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -246,10 +246,14 @@ function StepContainer(props: StepContainerProps) { className="overflow-x-scroll" components={{ pre: ({ node, ...props }) => { - return <CodeBlock children={props.children[0]} />; + return ( + <CodeBlock + children={(props.children[0] as any).props.children[0]} + /> + ); }, code: ({ node, ...props }) => { - return <StyledCode children={props.children[0]} />; + return <StyledCode children={props.children[0] as any} />; }, }} > diff --git a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts index 3d8e0a38..228e9a53 100644 --- a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts +++ b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts @@ -20,6 +20,8 @@ abstract class AbstractContinueGUIClientProtocol { abstract retryAtIndex(index: number): void; abstract deleteAtIndex(index: number): void; + + abstract deleteContextItemAtIndex(index: number): void; } export default AbstractContinueGUIClientProtocol; diff --git a/extension/react-app/src/hooks/useContinueGUIProtocol.ts b/extension/react-app/src/hooks/useContinueGUIProtocol.ts index f43a66ff..a0c38c0f 100644 --- a/extension/react-app/src/hooks/useContinueGUIProtocol.ts +++ b/extension/react-app/src/hooks/useContinueGUIProtocol.ts @@ -70,6 +70,10 @@ class ContinueGUIClientProtocol extends AbstractContinueGUIClientProtocol { deleteAtIndex(index: number) { this.messenger.send("delete_at_index", { index }); } + + deleteContextItemAtIndex(index: number) { + this.messenger.send("delete_context_item_at_index", { index }); + } } export default ContinueGUIClientProtocol; diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 39925fc5..658aa503 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -69,6 +69,7 @@ function GUI(props: GUIProps) { const [usingFastModel, setUsingFastModel] = useState(false); const [waitingForSteps, setWaitingForSteps] = useState(false); const [userInputQueue, setUserInputQueue] = useState<string[]>([]); + const [highlightedRanges, setHighlightedRanges] = useState([]); const [availableSlashCommands, setAvailableSlashCommands] = useState< { name: string; description: string }[] >([]); @@ -83,60 +84,6 @@ function GUI(props: GUIProps) { timeline: [ { step: { - name: "SequentialStep", - hide: true, - description: "Running step: SequentialStep", - system_message: null, - chat_context: [], - manage_own_chat_context: false, - steps: [ - { - name: "Welcome to Continue", - hide: false, - description: `Welcome to Continue`, - system_message: null, - chat_context: [], - manage_own_chat_context: false, - message: `# Welcome to Continue - - _If it's your first time using Continue, it can take up to a minute for the server to install._ - - Continue is not perfect, but a great tool to add to your toolbox. These are the tasks that Continue is currently best at: - - - Highlight a section of code and instruct Continue to refactor it, e.g. \`"/edit make this use more descriptive variable names"\` - - Ask questions of the open file, e.g. \`"/explain what is the purpose of each of these if statements?"\` - - Ask Continue to build the scaffolding of a new file from scratch, e.g. \`"add a React component for syntax highlighted code"\` - - You can use "slash commands" to directly instruct Continue what to do, or just enter a request and it will automatically decide next steps. To see the list of available slash commands, type '/'. - - If you highlight code, edits and explanations will be localized to the highlighted range. Otherwise, the currently open file is used. In both cases, the code is combined with the previous steps to construct the context. - `, - }, - { - name: "Welcome to Continue!", - hide: true, - description: "Welcome to Continue!", - system_message: null, - chat_context: [], - manage_own_chat_context: false, - }, - { - name: "StepsOnStartupStep", - hide: true, - description: "Running steps on startup", - system_message: null, - chat_context: [], - manage_own_chat_context: false, - }, - ], - }, - observation: null, - depth: 0, - deleted: false, - active: false, - }, - { - step: { name: "Welcome to Continue", hide: false, description: @@ -147,167 +94,13 @@ function GUI(props: GUIProps) { message: "Type '/' to see the list of available slash commands. If you highlight code, edits and explanations will be localized to the highlighted range. Otherwise, the currently open file is used. In both cases, the code is combined with the previous steps to construct the context.", }, - observation: { - text: "Type '/' to see the list of available slash commands. If you highlight code, edits and explanations will be localized to the highlighted range. Otherwise, the currently open file is used. In both cases, the code is combined with the previous steps to construct the context.", - }, - depth: 1, - deleted: false, - active: false, - }, - { - step: { - name: "Welcome to Continue!", - hide: true, - description: "Welcome to Continue!", - system_message: null, - chat_context: [], - manage_own_chat_context: false, - }, - observation: null, - depth: 1, - deleted: false, - active: false, - }, - { - step: { - name: "StepsOnStartupStep", - hide: true, - description: "Running steps on startup", - system_message: null, - chat_context: [], - manage_own_chat_context: false, - }, - observation: null, - depth: 1, + depth: 0, deleted: false, active: false, }, ], current_index: 3, } as any); - // { - // timeline: [ - // { - // step: { - // 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` and ```\nprint(sum(first, second))\n```\n- Testing\n- Testing 2\n- Testing 3", - // }, - // observation: { - // title: "ERROR FOUND", - // error: - // "Traceback (most recent call last):\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/main.py\", line 7, in <module>\n print(sum(first, second))\n ^^^^^^^^^^^^^^^^^^\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/sum.py\", line 2, in sum\n return a + b\n ~~^~~\nTypeError: unsupported operand type(s) for +: 'int' and 'str'", - // }, - // output: [ - // { - // traceback: { - // frames: [ - // { - // filepath: - // "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", - // lineno: 7, - // function: "<module>", - // code: "print(sum(first, second))", - // }, - // ], - // message: "unsupported operand type(s) for +: 'int' and 'str'", - // error_type: - // ' ^^^^^^^^^^^^^^^^^^\n File "/Users/natesesti/Desktop/continue/extension/examples/python/sum.py", line 2, in sum\n return a + b\n ~~^~~\nTypeError', - // full_traceback: - // "Traceback (most recent call last):\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/main.py\", line 7, in <module>\n print(sum(first, second))\n ^^^^^^^^^^^^^^^^^^\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/sum.py\", line 2, in sum\n return a + b\n ~~^~~\nTypeError: unsupported operand type(s) for +: 'int' and 'str'", - // }, - // }, - // null, - // ], - // }, - // { - // step: { - // name: "EditCodeStep", - // range_in_files: [ - // { - // filepath: - // "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", - // range: { - // start: { - // line: 0, - // character: 0, - // }, - // end: { - // line: 6, - // character: 25, - // }, - // }, - // }, - // ], - // prompt: - // "I ran into this problem with my Python code:\n\n Traceback (most recent call last):\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/main.py\", line 7, in <module>\n print(sum(first, second))\n ^^^^^^^^^^^^^^^^^^\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/sum.py\", line 2, in sum\n return a + b\n ~~^~~\nTypeError: unsupported operand type(s) for +: 'int' and 'str'\n\n Below are the files that might need to be fixed:\n\n {code}\n\n This is what the code should be in order to avoid the problem:\n", - // description: - // "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py` and\n```python\nprint(sum(first, second))\n```\n- Testing\n- Testing 2\n- Testing 3", - // }, - // output: [ - // null, - // { - // reversible: true, - // actions: [ - // { - // reversible: true, - // filesystem: {}, - // filepath: - // "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", - // range: { - // start: { - // line: 0, - // character: 0, - // }, - // end: { - // line: 6, - // character: 25, - // }, - // }, - // replacement: - // "\nfrom sum import sum\n\nfirst = 1\nsecond = 2\n\nprint(sum(first, second))", - // }, - // ], - // }, - // ], - // }, - // { - // active: false, - // step: { - // name: "SolveTracebackStep", - // traceback: { - // frames: [ - // { - // filepath: - // "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", - // lineno: 7, - // function: "<module>", - // code: "print(sum(first, second))", - // }, - // ], - // message: "unsupported operand type(s) for +: 'int' and 'str'", - // error_type: - // ' ^^^^^^^^^^^^^^^^^^\n File "/Users/natesesti/Desktop/continue/extension/examples/python/sum.py", line 2, in sum\n return a + b\n ~~^~~\nTypeError', - // full_traceback: - // "Traceback (most recent call last):\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/main.py\", line 7, in <module>\n print(sum(first, second))\n ^^^^^^^^^^^^^^^^^^\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/sum.py\", line 2, in sum\n return a + b\n ~~^~~\nTypeError: unsupported operand type(s) for +: 'int' and 'str'", - // }, - // description: "Running step: SolveTracebackStep", - // }, - // output: [null, null], - // }, - // { - // step: { - // name: "RunCodeStep", - // cmd: "python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py", - // description: - // "Run `python3 /Users/natesesti/Desktop/continue/extension/examples/python/main.py`", - // }, - // output: [null, null], - // }, - // ], - // current_index: 3, - // } as any); const [showFeedbackDialog, setShowFeedbackDialog] = useState(false); @@ -356,6 +149,7 @@ function GUI(props: GUIProps) { topGuiDivRef.current?.offsetHeight - window.scrollY < 100; setWaitingForSteps(state.active); setHistory(state.history); + setHighlightedRanges(state.highlighted_ranges); setUserInputQueue(state.user_input_queue); setStepsOpen((prev) => { const nextStepsOpen = [...prev]; @@ -392,6 +186,13 @@ function GUI(props: GUIProps) { const mainTextInputRef = useRef<HTMLInputElement>(null); + const deleteContextItem = useCallback( + (idx: number) => { + client?.deleteContextItemAtIndex(idx); + }, + [client] + ); + useEffect(() => { if (mainTextInputRef.current) { mainTextInputRef.current.focus(); @@ -533,6 +334,8 @@ function GUI(props: GUIProps) { }} onInputValueChange={() => {}} items={availableSlashCommands} + highlightedCodeSections={highlightedRanges} + deleteContextItem={deleteContextItem} /> <ContinueButton onClick={onMainTextInput} /> </TopGUIDiv> |