From d802dae10b26f59893380829feea3104b0650e14 Mon Sep 17 00:00:00 2001 From: Ty Dunn Date: Tue, 4 Jul 2023 21:14:35 -0700 Subject: new stop --- extension/package.json | 1 + 1 file changed, 1 insertion(+) (limited to 'extension/package.json') diff --git a/extension/package.json b/extension/package.json index 184d16e2..f39e7bd7 100644 --- a/extension/package.json +++ b/extension/package.json @@ -242,6 +242,7 @@ "@segment/analytics-node": "^0.0.1-beta.16", "@sentry/node": "^7.57.0", "@styled-icons/heroicons-outline": "^10.47.0", + "@styled-icons/heroicons-solid": "^10.47.0", "@vitejs/plugin-react-swc": "^3.3.2", "axios": "^1.2.5", "downshift": "^7.6.0", -- cgit v1.2.3-70-g09d2 From 8f93431f346d72a790b16a00d577c8f3d8c761b3 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 4 Jul 2023 22:39:52 -0700 Subject: side-by-side diff editor --- continuedev/src/continuedev/steps/core/core.py | 82 +++++++++++------- extension/package.json | 10 +++ extension/src/commands.ts | 4 + extension/src/continueIdeClient.ts | 38 ++------- extension/src/diffs.ts | 114 +++++++++++++++++++++++++ extension/src/lang-server/codeLens.ts | 40 ++++++++- 6 files changed, 221 insertions(+), 67 deletions(-) create mode 100644 extension/src/diffs.ts (limited to 'extension/package.json') diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index b9f0da35..b215b317 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -295,6 +295,17 @@ class DefaultModelEditCodeStep(Step): prompt = self.compile_prompt(file_prefix, contents, file_suffix, sdk) full_file_contents_lines = full_file_contents.split("\n") + async def sendDiffUpdate(lines: List[str], sdk: ContinueSDK): + nonlocal full_file_contents_lines, rif + + completion = "\n".join(lines) + + full_prefix_lines = full_file_contents_lines[:rif.range.start.line] + full_suffix_lines = full_file_contents_lines[rif.range.end.line + 1:] + new_file_contents = "\n".join( + full_prefix_lines) + "\n" + completion + "\n" + "\n".join(full_suffix_lines) + await sdk.ide.showDiff(rif.filepath, new_file_contents) + # Important state variables # ------------------------- original_lines = [] if rif.contents == "" else rif.contents.split("\n") @@ -435,16 +446,16 @@ class DefaultModelEditCodeStep(Step): chunk_lines.pop() # because this will be an empty string else: unfinished_line = chunk_lines.pop() - lines.extend(chunk_lines) + lines.extend(map(lambda l: common_whitespace + l, chunk_lines)) + + if True: + await sendDiffUpdate(lines, sdk) # Deal with newly accumulated lines for line in chunk_lines: # Trailing whitespace doesn't matter line = line.rstrip() - # Add the common whitespace that was removed before prompting - line = common_whitespace + line - # Lines that should signify the end of generation if self.is_end_line(line): break @@ -463,7 +474,9 @@ class DefaultModelEditCodeStep(Step): break # If none of the above, insert the line! - await handle_generated_line(line) + if False: + await handle_generated_line(line) + completion_lines_covered += 1 current_line_in_file += 1 @@ -475,34 +488,37 @@ class DefaultModelEditCodeStep(Step): completion_lines_covered += 1 current_line_in_file += 1 - # If the current block isn't empty, add that suggestion - if len(current_block_lines) > 0: - # We have a chance to back-track here for blank lines that are repeats of the end of the original - # Don't want to have the same ending in both the original and the generated, can just leave it there - num_to_remove = 0 - for i in range(-1, -len(current_block_lines) - 1, -1): - if len(original_lines_below_previous_blocks) == 0: - break - if current_block_lines[i] == original_lines_below_previous_blocks[-1]: - num_to_remove += 1 - original_lines_below_previous_blocks.pop() - else: - break - current_block_lines = current_block_lines[:- - num_to_remove] if num_to_remove > 0 else current_block_lines - - # It's also possible that some lines match at the beginning of the block - # while len(current_block_lines) > 0 and len(original_lines_below_previous_blocks) > 0 and current_block_lines[0] == original_lines_below_previous_blocks[0]: - # current_block_lines.pop(0) - # original_lines_below_previous_blocks.pop(0) - # current_block_start += 1 - - await sdk.ide.showSuggestion(FileEdit( - filepath=rif.filepath, - range=Range.from_shorthand( - current_block_start, 0, current_block_start + len(original_lines_below_previous_blocks), 0), - replacement="\n".join(current_block_lines) - )) + await sendDiffUpdate(lines, sdk) + + if False: + # If the current block isn't empty, add that suggestion + if len(current_block_lines) > 0: + # We have a chance to back-track here for blank lines that are repeats of the end of the original + # Don't want to have the same ending in both the original and the generated, can just leave it there + num_to_remove = 0 + for i in range(-1, -len(current_block_lines) - 1, -1): + if len(original_lines_below_previous_blocks) == 0: + break + if current_block_lines[i] == original_lines_below_previous_blocks[-1]: + num_to_remove += 1 + original_lines_below_previous_blocks.pop() + else: + break + current_block_lines = current_block_lines[:- + num_to_remove] if num_to_remove > 0 else current_block_lines + + # It's also possible that some lines match at the beginning of the block + # while len(current_block_lines) > 0 and len(original_lines_below_previous_blocks) > 0 and current_block_lines[0] == original_lines_below_previous_blocks[0]: + # current_block_lines.pop(0) + # original_lines_below_previous_blocks.pop(0) + # current_block_start += 1 + + await sdk.ide.showSuggestion(FileEdit( + filepath=rif.filepath, + range=Range.from_shorthand( + current_block_start, 0, current_block_start + len(original_lines_below_previous_blocks), 0), + replacement="\n".join(current_block_lines) + )) # Record the completion completion = "\n".join(lines) diff --git a/extension/package.json b/extension/package.json index 87dd7ba6..461f5721 100644 --- a/extension/package.json +++ b/extension/package.json @@ -86,6 +86,16 @@ "category": "Continue", "title": "Reject Suggestion" }, + { + "command": "continue.acceptDiff", + "category": "Continue", + "title": "Accept Diff" + }, + { + "command": "continue.rejectDiff", + "category": "Continue", + "title": "Reject Diff" + }, { "command": "continue.acceptAllSuggestions", "category": "Continue", diff --git a/extension/src/commands.ts b/extension/src/commands.ts index 8072353b..4414a171 100644 --- a/extension/src/commands.ts +++ b/extension/src/commands.ts @@ -12,6 +12,8 @@ import { acceptAllSuggestionsCommand, rejectAllSuggestionsCommand, } from "./suggestions"; + +import { acceptDiffCommand, rejectDiffCommand } from "./diffs"; import * as bridge from "./bridge"; import { debugPanelWebview } from "./debugPanel"; import { sendTelemetryEvent, TelemetryEvent } from "./telemetry"; @@ -51,6 +53,8 @@ const commandsMap: { [command: string]: (...args: any) => any } = { "continue.suggestionUp": suggestionUpCommand, "continue.acceptSuggestion": acceptSuggestionCommand, "continue.rejectSuggestion": rejectSuggestionCommand, + "continue.acceptDiff": acceptDiffCommand, + "continue.rejectDiff": rejectDiffCommand, "continue.acceptAllSuggestions": acceptAllSuggestionsCommand, "continue.rejectAllSuggestions": rejectAllSuggestionsCommand, "continue.focusContinueInput": async () => { diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index b9969858..90547edc 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -15,6 +15,10 @@ import { import { FileEditWithFullContents } from "../schema/FileEditWithFullContents"; import fs = require("fs"); import { WebsocketMessenger } from "./util/messenger"; +import * as path from "path"; +import * as os from "os"; +import { diffManager } from "./diffs"; + class IdeProtocolClient { private messenger: WebsocketMessenger | null = null; private readonly context: vscode.ExtensionContext; @@ -239,40 +243,8 @@ class IdeProtocolClient { ); } - contentProvider: vscode.Disposable | null = null; - showDiff(filepath: string, replacement: string) { - const myProvider = new (class - implements vscode.TextDocumentContentProvider - { - onDidChangeEmitter = new vscode.EventEmitter(); - onDidChange = this.onDidChangeEmitter.event; - provideTextDocumentContent = (uri: vscode.Uri) => { - return replacement; - }; - })(); - this.contentProvider = vscode.workspace.registerTextDocumentContentProvider( - "continueDiff", - myProvider - ); - - // Call the event fire - const diffFilename = `continueDiff://${filepath}`; - myProvider.onDidChangeEmitter.fire(vscode.Uri.parse(diffFilename)); - - const leftUri = vscode.Uri.file(filepath); - const rightUri = vscode.Uri.parse(diffFilename); - const title = "Continue Diff"; - vscode.commands - .executeCommand("vscode.diff", leftUri, rightUri, title) - .then( - () => { - console.log("Diff view opened successfully"); - }, - (error) => { - console.error("Error opening diff view:", error); - } - ); + diffManager.writeDiff(filepath, replacement); } openFile(filepath: string) { diff --git a/extension/src/diffs.ts b/extension/src/diffs.ts new file mode 100644 index 00000000..4bd072cf --- /dev/null +++ b/extension/src/diffs.ts @@ -0,0 +1,114 @@ +import * as os from "os"; +import * as path from "path"; +import * as fs from "fs"; +import * as vscode from "vscode"; + +interface DiffInfo { + originalFilepath: string; + newFilepath: string; + editor?: vscode.TextEditor; +} + +export const DIFF_DIRECTORY = path.join(os.homedir(), ".continue", "diffs"); + +class DiffManager { + // Create a temporary file in the global .continue directory which displays the updated version + // Doing this because virtual files are read-only + private diffs: Map = new Map(); + + constructor() { + // Make sure the diff directory exists + if (!fs.existsSync(DIFF_DIRECTORY)) { + fs.mkdirSync(DIFF_DIRECTORY, { + recursive: true, + }); + } + } + + private escapeFilepath(filepath: string): string { + return filepath.replace(/\\/g, "_").replace(/\//g, "_"); + } + + private openDiffEditor( + originalFilepath: string, + newFilepath: string, + newContent: string + ): vscode.TextEditor { + const rightUri = vscode.Uri.parse(newFilepath); + const leftUri = vscode.Uri.file(originalFilepath); + const title = "Continue Diff"; + vscode.commands.executeCommand("vscode.diff", leftUri, rightUri, title); + + const editor = vscode.window.activeTextEditor; + if (!editor) { + throw new Error("No active text editor found for Continue Diff"); + } + return editor; + } + + writeDiff(originalFilepath: string, newContent: string): string { + // Create or update existing diff + const newFilepath = path.join( + DIFF_DIRECTORY, + this.escapeFilepath(originalFilepath) + ); + fs.writeFileSync(newFilepath, newContent); + + // Open the diff editor if this is a new diff + if (!this.diffs.has(originalFilepath)) { + const diffInfo: DiffInfo = { + originalFilepath, + newFilepath, + }; + diffInfo.editor = this.openDiffEditor( + originalFilepath, + newFilepath, + newContent + ); + this.diffs.set(originalFilepath, diffInfo); + } + return newFilepath; + } + + cleanUpDiff(diffInfo: DiffInfo) { + // Close the editor, remove the record, delete the file + if (diffInfo.editor) { + vscode.window.showTextDocument(diffInfo.editor.document); + vscode.commands.executeCommand("workbench.action.closeActiveEditor"); + } + this.diffs.delete(diffInfo.originalFilepath); + fs.unlinkSync(diffInfo.newFilepath); + } + + acceptDiff(originalFilepath: string) { + // Get the diff info, copy new file to original, then delete from record and close the corresponding editor + const diffInfo = this.diffs.get(originalFilepath); + if (!diffInfo) { + return; + } + fs.writeFileSync( + diffInfo.originalFilepath, + fs.readFileSync(diffInfo.newFilepath) + ); + this.cleanUpDiff(diffInfo); + } + + rejectDiff(originalFilepath: string) { + const diffInfo = this.diffs.get(originalFilepath); + if (!diffInfo) { + return; + } + + this.cleanUpDiff(diffInfo); + } +} + +export const diffManager = new DiffManager(); + +export async function acceptDiffCommand(originalFilepath: string) { + diffManager.acceptDiff(originalFilepath); +} + +export async function rejectDiffCommand(originalFilepath: string) { + diffManager.rejectDiff(originalFilepath); +} diff --git a/extension/src/lang-server/codeLens.ts b/extension/src/lang-server/codeLens.ts index 3bd4f153..08435a3b 100644 --- a/extension/src/lang-server/codeLens.ts +++ b/extension/src/lang-server/codeLens.ts @@ -1,6 +1,8 @@ import * as vscode from "vscode"; import { editorToSuggestions, editorSuggestionsLocked } from "../suggestions"; - +import * as path from "path"; +import * as os from "os"; +import { DIFF_DIRECTORY } from "../diffs"; class SuggestionsCodeLensProvider implements vscode.CodeLensProvider { public provideCodeLenses( document: vscode.TextDocument, @@ -60,15 +62,51 @@ class SuggestionsCodeLensProvider implements vscode.CodeLensProvider { } } +class DiffViewerCodeLensProvider implements vscode.CodeLensProvider { + public provideCodeLenses( + document: vscode.TextDocument, + token: vscode.CancellationToken + ): vscode.CodeLens[] | Thenable { + if (path.dirname(document.uri.fsPath) !== DIFF_DIRECTORY) { + return []; + } else { + const codeLenses: vscode.CodeLens[] = []; + const range = new vscode.Range(0, 0, 0, 0); + codeLenses.push( + new vscode.CodeLens(range, { + title: "Accept ✅", + command: "continue.acceptDiff", + arguments: [document.uri.fsPath], + }), + new vscode.CodeLens(range, { + title: "Reject ❌", + command: "continue.rejectDiff", + arguments: [document.uri.fsPath], + }) + ); + return codeLenses; + } + } +} + +let diffsCodeLensDisposable: vscode.Disposable | undefined = undefined; let suggestionsCodeLensDisposable: vscode.Disposable | undefined = undefined; export function registerAllCodeLensProviders(context: vscode.ExtensionContext) { if (suggestionsCodeLensDisposable) { suggestionsCodeLensDisposable.dispose(); } + if (diffsCodeLensDisposable) { + diffsCodeLensDisposable.dispose(); + } suggestionsCodeLensDisposable = vscode.languages.registerCodeLensProvider( "*", new SuggestionsCodeLensProvider() ); + diffsCodeLensDisposable = vscode.languages.registerCodeLensProvider( + "*", + new DiffViewerCodeLensProvider() + ); context.subscriptions.push(suggestionsCodeLensDisposable); + context.subscriptions.push(diffsCodeLensDisposable); } -- cgit v1.2.3-70-g09d2 From 461fd4df95c31010871cc4ea7707606fb3a14fb4 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Wed, 5 Jul 2023 01:17:58 -0700 Subject: test custom command, don't run shell command --- continuedev/src/continuedev/core/config.py | 5 ++++- continuedev/src/continuedev/steps/chat.py | 6 +----- extension/package-lock.json | 4 ++-- extension/package.json | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) (limited to 'extension/package.json') diff --git a/continuedev/src/continuedev/core/config.py b/continuedev/src/continuedev/core/config.py index 9e8541dc..8f7e0b8c 100644 --- a/continuedev/src/continuedev/core/config.py +++ b/continuedev/src/continuedev/core/config.py @@ -71,7 +71,10 @@ class ContinueConfig(BaseModel): allow_anonymous_telemetry: Optional[bool] = True default_model: Literal["gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-4"] = 'gpt-4' - custom_commands: Optional[List[CustomCommand]] = [] + custom_commands: Optional[List[CustomCommand]] = [CustomCommand( + name="test", + prompt="Write a comprehensive set of unit tests for the selected code. It should setup, run tests that check for correctness including important edge cases, and teardown. Ensure that the tests are complete and sophisticated. Give the tests just as chat output, don't edit any file.", + )] slash_commands: Optional[List[SlashCommand]] = DEFAULT_SLASH_COMMANDS on_traceback: Optional[List[OnTracebackSteps]] = [ OnTracebackSteps(step_name="DefaultOnTracebackStep")] diff --git a/continuedev/src/continuedev/steps/chat.py b/continuedev/src/continuedev/steps/chat.py index db3f9d7f..8f88244c 100644 --- a/continuedev/src/continuedev/steps/chat.py +++ b/continuedev/src/continuedev/steps/chat.py @@ -107,12 +107,8 @@ class RunTerminalCommandStep(Step): description: str = "Run a terminal command." command: str - async def describe(self, models: Models) -> Coroutine[Any, Any, Coroutine[str, None, None]]: - return f"Ran the terminal command `{self.command}`." - async def run(self, sdk: ContinueSDK): - await sdk.wait_for_user_confirmation(f"Run the following terminal command?\n\n```bash\n{self.command}\n```") - await sdk.run(self.command) + self.description = f"Copy this command and run in your terminal:\n\n```bash\n{self.command}\n```" class ViewDirectoryTreeStep(Step): diff --git a/extension/package-lock.json b/extension/package-lock.json index 2dd7d6d4..82c28a90 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.0.108", + "version": "0.0.109", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "continue", - "version": "0.0.108", + "version": "0.0.109", "license": "Apache-2.0", "dependencies": { "@electron/rebuild": "^3.2.10", diff --git a/extension/package.json b/extension/package.json index d4850671..001a696e 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.108", + "version": "0.0.109", "publisher": "Continue", "engines": { "vscode": "^1.67.0" -- cgit v1.2.3-70-g09d2 From c5cee3f4c40e7ff00265929b3a593d62b4b50ada Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Wed, 5 Jul 2023 01:51:46 -0700 Subject: details --- continuedev/src/continuedev/core/policy.py | 64 ++++++++++++---------- extension/package-lock.json | 4 +- extension/package.json | 2 +- extension/react-app/src/components/ComboBox.tsx | 2 +- .../react-app/src/components/StepContainer.tsx | 12 ++-- .../src/components/UserInputContainer.tsx | 10 ++-- extension/react-app/src/tabs/gui.tsx | 18 +++--- 7 files changed, 61 insertions(+), 51 deletions(-) (limited to 'extension/package.json') diff --git a/continuedev/src/continuedev/core/policy.py b/continuedev/src/continuedev/core/policy.py index b0853380..ef753ee4 100644 --- a/continuedev/src/continuedev/core/policy.py +++ b/continuedev/src/continuedev/core/policy.py @@ -1,5 +1,5 @@ from textwrap import dedent -from typing import List, Tuple, Type +from typing import List, Tuple, Type, Union from ..steps.welcome import WelcomeStep from .config import ContinueConfig @@ -22,6 +22,34 @@ from ..libs.util.step_name_to_steps import get_step_from_name from ..steps.custom_command import CustomCommandStep +def parse_slash_command(inp: str, config: ContinueConfig) -> Union[None, Step]: + """ + Parses a slash command, returning the command name and the rest of the input. + """ + if inp.startswith("/"): + command_name = inp.split(" ")[0] + after_command = " ".join(inp.split(" ")[1:]) + + for slash_command in config.slash_commands: + if slash_command.name == command_name[1:]: + params = slash_command.params + params["user_input"] = after_command + return get_step_from_name(slash_command.step_name, params) + return None + + +def parse_custom_command(inp: str, config: ContinueConfig) -> Union[None, Step]: + command_name = inp.split(" ")[0] + after_command = " ".join(inp.split(" ")[1:]) + for custom_cmd in config.custom_commands: + if custom_cmd.name == command_name[1:]: + slash_command = parse_slash_command(custom_cmd.prompt, config) + if slash_command is not None: + return slash_command + return CustomCommandStep(name=custom_cmd.name, prompt=custom_cmd.prompt, user_input=after_command) + return None + + class DemoPolicy(Policy): ran_code_last: bool = False @@ -46,34 +74,14 @@ class DemoPolicy(Policy): # This could be defined with ObservationTypePolicy. Ergonomics not right though. user_input = observation.user_input - if user_input.startswith("/"): - command_name = user_input.split(" ")[0] - after_command = " ".join(user_input.split(" ")[1:]) - for slash_command in config.slash_commands: - if slash_command.name == command_name[1:]: - params = slash_command.params - params["user_input"] = after_command - return get_step_from_name(slash_command.step_name, params) + slash_command = parse_slash_command(user_input) + if slash_command is not None: + return slash_command - for custom_cmd in config.custom_commands: - if custom_cmd.name == command_name[1:]: - return CustomCommandStep(name=custom_cmd.name, prompt=custom_cmd.prompt, user_input=after_command) + custom_command = parse_custom_command(user_input) + if custom_command is not None: + return custom_command - # return EditHighlightedCodeStep(user_input=user_input) return ChatWithFunctions(user_input=user_input) - return NLDecisionStep(user_input=user_input, steps=[ - (EditHighlightedCodeStep(user_input=user_input), - "Edit the highlighted code"), - # AnswerQuestionChroma(question=user_input), - # EditFileChroma(request=user_input), - (SimpleChatStep(user_input=user_input), - "Respond to the user with a chat message. Can answer questions about code or anything else."), - ], default_step=EditHighlightedCodeStep(user_input=user_input)) - - state = history.get_current() - if observation is not None and isinstance(observation, TracebackObservation): - self.ran_code_last = False - return SolveTracebackStep(traceback=observation.traceback) - else: - return None + return None diff --git a/extension/package-lock.json b/extension/package-lock.json index 82c28a90..ce1a42ee 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.0.109", + "version": "0.0.110", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "continue", - "version": "0.0.109", + "version": "0.0.110", "license": "Apache-2.0", "dependencies": { "@electron/rebuild": "^3.2.10", diff --git a/extension/package.json b/extension/package.json index 001a696e..607c2ca6 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.109", + "version": "0.0.110", "publisher": "Continue", "engines": { "vscode": "^1.67.0" diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index 97f5b57e..73b7cc2d 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -324,7 +324,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { /> ))} - + Highlight code to include as context. Currently open file included by default. {highlightedCodeSections.length === 0 && ""} diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index 183ffeef..2aed2e72 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -11,11 +11,9 @@ import { ChevronDown, ChevronRight, ArrowPath, - XMark + XMark, } from "@styled-icons/heroicons-outline"; -import { - Stop, -} from "@styled-icons/heroicons-solid"; +import { Stop } from "@styled-icons/heroicons-solid"; import { HistoryNode } from "../../../schema/HistoryNode"; import ReactMarkdown from "react-markdown"; import HeaderButtonWithText from "./HeaderButtonWithText"; @@ -213,7 +211,11 @@ function StepContainer(props: StepContainerProps) { text={props.historyNode.active ? "Stop" : "Delete"} active={props.historyNode.active} > - {props.historyNode.active ? :} + {props.historyNode.active ? ( + + ) : ( + + )} {props.historyNode.observation?.error ? ( ` - background-color: rgb(50 50 50); +const StyledDiv = styled.div` + background-color: rgb(45 45 45); padding: 8px; padding-left: 16px; padding-right: 16px; @@ -24,14 +24,12 @@ const StyledDiv = styled.div<{ hidden: boolean }>` font-size: 13px; display: flex; align-items: center; - visibility: ${(props) => (props.hidden ? "hidden" : "visible")}; - height: ${(props) => (props.hidden ? "0px" : "auto")}; `; const UserInputContainer = (props: UserInputContainerProps) => { return ( -