import styled from "styled-components"; import { defaultBorderRadius, vscBackground, Loader, MainTextInput, } from "../components"; import ContinueButton from "../components/ContinueButton"; import { useCallback, useEffect, useRef, useState } from "react"; import { History } from "../../../schema/History"; import { HistoryNode } from "../../../schema/HistoryNode"; import StepContainer from "../components/StepContainer"; import useContinueGUIProtocol from "../hooks/useWebsocket"; let TopGUIDiv = styled.div` display: grid; grid-template-columns: 1fr; background-color: ${vscBackground}; `; let UserInputQueueItem = styled.div` border-radius: ${defaultBorderRadius}; color: gray; padding: 8px; margin: 8px; text-align: center; `; interface GUIProps { firstObservation?: any; } function GUI(props: GUIProps) { const [waitingForSteps, setWaitingForSteps] = useState(false); const [userInputQueue, setUserInputQueue] = useState([]); const [history, setHistory] = useState(); // { // 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`", // }, // observation: { // title: "ERROR FOUND", // error: // "Traceback (most recent call last):\n File \"/Users/natesesti/Desktop/continue/extension/examples/python/main.py\", line 7, in \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: "", // 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 \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 \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: // "Editing files: /Users/natesesti/Desktop/continue/extension/examples/python/main.py", // }, // 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))", // }, // ], // }, // ], // }, // { // step: { // name: "SolveTracebackStep", // traceback: { // frames: [ // { // filepath: // "/Users/natesesti/Desktop/continue/extension/examples/python/main.py", // lineno: 7, // function: "", // 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 \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: 0, // } as any); const topGuiDivRef = useRef(null); const client = useContinueGUIProtocol(); const scrollToBottom = useCallback(() => { if (topGuiDivRef.current) { setTimeout(() => { window.scrollTo({ top: window.outerHeight, behavior: "smooth", }); }, 100); } }, [topGuiDivRef.current]); useEffect(() => { console.log("CLIENT ON STATE UPDATE: ", client, client?.onStateUpdate); client?.onStateUpdate((state) => { console.log("Received state update: ", state); setWaitingForSteps(state.active); setHistory(state.history); setUserInputQueue(state.user_input_queue); scrollToBottom(); }); }, [client]); useEffect(() => { scrollToBottom(); }, [waitingForSteps]); const mainTextInputRef = useRef(null); useEffect(() => { if (mainTextInputRef.current) { mainTextInputRef.current.focus(); let handler = (event: any) => { if (event.data.type === "focusContinueInput") { mainTextInputRef.current?.focus(); } }; window.addEventListener("message", handler); return () => { window.removeEventListener("message", handler); }; } }, [mainTextInputRef]); const onMainTextInput = () => { if (mainTextInputRef.current) { if (!client) return; let input = mainTextInputRef.current.value; if ( history && history.timeline[history.current_index].step.name === "Waiting for user input" ) { if (input.trim() === "") return; onStepUserInput(input, history!.current_index); } else if ( history && history.timeline[history.current_index].step.name === "Waiting for user confirmation" ) { onStepUserInput("ok", history!.current_index); } else { if (input.trim() === "") return; client.sendMainInput(input); setUserInputQueue((queue) => { return [...queue, input]; }); } mainTextInputRef.current.value = ""; mainTextInputRef.current.style.height = ""; } setWaitingForSteps(true); }; 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 ( { 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); }} /> ); })} {waitingForSteps && }
{userInputQueue.map((input) => { return {input}; })}
{ if (e.key === "Enter") { onMainTextInput(); e.stopPropagation(); e.preventDefault(); } }} rows={1} onChange={() => { const textarea = mainTextInputRef.current!; textarea.style.height = ""; /* Reset the height*/ textarea.style.height = `${Math.min( textarea.scrollHeight - 15, 500 )}px`; }} />
); } export default GUI;