From 94341653cae5b9af6e33f480847dfb562aa7578c Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Wed, 21 Jun 2023 14:02:56 -0700 Subject: first slightly working version of suggestions --- continuedev/src/continuedev/server/ide.py | 6 +- continuedev/src/continuedev/server/ide_protocol.py | 2 +- continuedev/src/continuedev/steps/core/core.py | 448 ++++++++++----------- 3 files changed, 226 insertions(+), 230 deletions(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/server/ide.py b/continuedev/src/continuedev/server/ide.py index c83fbc8a..c2ebaccf 100644 --- a/continuedev/src/continuedev/server/ide.py +++ b/continuedev/src/continuedev/server/ide.py @@ -146,8 +146,10 @@ class IdeProtocolServer(AbstractIdeProtocolServer): # ------------------------------- # # Request actions in IDE, doesn't matter which Session - def showSuggestion(): - pass + async def showSuggestion(self, file_edit: FileEdit): + await self._send_json("showSuggestion", { + "edit": file_edit.dict() + }) async def setFileOpen(self, filepath: str, open: bool = True): # Autopilot needs access to this. diff --git a/continuedev/src/continuedev/server/ide_protocol.py b/continuedev/src/continuedev/server/ide_protocol.py index 2dcedc30..79820c36 100644 --- a/continuedev/src/continuedev/server/ide_protocol.py +++ b/continuedev/src/continuedev/server/ide_protocol.py @@ -12,7 +12,7 @@ class AbstractIdeProtocolServer(ABC): """Handle a json message""" @abstractmethod - def showSuggestion(): + def showSuggestion(self, file_edit: FileEdit): """Show a suggestion to the user""" @abstractmethod diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 71a5b5b2..eb6a00c6 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -159,253 +159,247 @@ class DefaultModelEditCodeStep(Step): self.name = await models.gpt35.complete(f"Write a very short title to describe this requested change: '{self.user_input}'. This is the title:") return f"`{self.user_input}`\n\n" + description - async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: - self.description = f"`{self.user_input}`" - await sdk.update_ui() - - rif_with_contents = [] - for range_in_file in map(lambda x: RangeInFile( - filepath=x.filepath, - # Only consider the range line-by-line. Maybe later don't if it's only a single line. - range=x.range.to_full_lines() - ), self.range_in_files): - file_contents = await sdk.ide.readRangeInFile(range_in_file) - rif_with_contents.append( - RangeInFileWithContents.from_range_in_file(range_in_file, file_contents)) - - rif_dict = {} - for rif in rif_with_contents: - rif_dict[rif.filepath] = rif.contents - - for rif in rif_with_contents: - await sdk.ide.setFileOpen(rif.filepath) - - model_to_use = sdk.models.default - - full_file_contents = await sdk.ide.readFile(rif.filepath) - - full_file_contents_lst = full_file_contents.split("\n") - - max_start_line = rif.range.start.line - min_end_line = rif.range.end.line - cur_start_line = 0 - cur_end_line = len(full_file_contents_lst) - 1 - - def cut_context(model_to_use, total_tokens, cur_start_line, cur_end_line): - - if total_tokens > MAX_TOKENS_FOR_MODEL[model_to_use.name]: - while cur_end_line > min_end_line: - total_tokens -= model_to_use.count_tokens( - full_file_contents_lst[cur_end_line]) - cur_end_line -= 1 - if total_tokens < MAX_TOKENS_FOR_MODEL[model_to_use.name]: - return cur_start_line, cur_end_line - - if total_tokens > MAX_TOKENS_FOR_MODEL[model_to_use.name]: - while cur_start_line < max_start_line: - cur_start_line += 1 - total_tokens -= model_to_use.count_tokens( - full_file_contents_lst[cur_end_line]) - if total_tokens < MAX_TOKENS_FOR_MODEL[model_to_use.name]: - return cur_start_line, cur_end_line - - return cur_start_line, cur_end_line - - if model_to_use.name == "gpt-4": - - total_tokens = model_to_use.count_tokens(full_file_contents + self._prompt) - cur_start_line, cur_end_line = cut_context( - model_to_use, total_tokens, cur_start_line, cur_end_line) - - elif model_to_use.name == "gpt-3.5-turbo" or model_to_use.name == "gpt-3.5-turbo-16k": - - if sdk.models.gpt35.count_tokens(full_file_contents) > MAX_TOKENS_FOR_MODEL["gpt-3.5-turbo"]: - - model_to_use = sdk.models.gpt3516k - total_tokens = model_to_use.count_tokens( - full_file_contents + self._prompt) - cur_start_line, cur_end_line = cut_context( - model_to_use, total_tokens, cur_start_line, cur_end_line) - - else: - - raise Exception("Unknown default model") + async def get_prompt_parts(self, rif: RangeInFileWithContents, sdk: ContinueSDK, full_file_contents: str): + # If using 3.5 and overflows, upgrade to 3.5.16k + model_to_use = sdk.models.default + if model_to_use.name == "gpt-3.5-turbo": + if sdk.models.gpt35.count_tokens(full_file_contents) > MAX_TOKENS_FOR_MODEL["gpt-3.5-turbo"]: + model_to_use = sdk.models.gpt3516k + + # Remove tokens from the end first, and then the start to clear space + # This part finds the start and end lines + full_file_contents_lst = full_file_contents.split("\n") + max_start_line = rif.range.start.line + min_end_line = rif.range.end.line + cur_start_line = 0 + cur_end_line = len(full_file_contents_lst) - 1 + + total_tokens = model_to_use.count_tokens( + full_file_contents + self._prompt) + + if total_tokens > MAX_TOKENS_FOR_MODEL[model_to_use.name]: + while cur_end_line > min_end_line: + total_tokens -= model_to_use.count_tokens( + full_file_contents_lst[cur_end_line]) + cur_end_line -= 1 + if total_tokens < MAX_TOKENS_FOR_MODEL[model_to_use.name]: + return cur_start_line, cur_end_line + + if total_tokens > MAX_TOKENS_FOR_MODEL[model_to_use.name]: + while cur_start_line < max_start_line: + cur_start_line += 1 + total_tokens -= model_to_use.count_tokens( + full_file_contents_lst[cur_end_line]) + if total_tokens < MAX_TOKENS_FOR_MODEL[model_to_use.name]: + return cur_start_line, cur_end_line + + # Now use the found start/end lines to get the prefix and suffix strings + file_prefix = "\n".join( + full_file_contents_lst[cur_start_line:max_start_line]) + file_suffix = "\n".join( + full_file_contents_lst[min_end_line:cur_end_line - 1]) + + # Move any surrounding blank line in rif.contents to the prefix/suffix + # TODO: Keep track of start line of the range, because it's needed below for offset stuff + rif_start_line = rif.range.start.line + if len(rif.contents) > 0: + first_line = rif.contents.splitlines(keepends=True)[0] + while first_line.strip() == "": + file_prefix += first_line + rif.contents = rif.contents[len(first_line):] + first_line = rif.contents.splitlines(keepends=True)[0] - code_before = "\n".join( - full_file_contents_lst[cur_start_line:max_start_line]) - code_after = "\n".join( - full_file_contents_lst[min_end_line:cur_end_line - 1]) + last_line = rif.contents.splitlines(keepends=True)[-1] + while last_line.strip() == "": + file_suffix = last_line + file_suffix + rif.contents = rif.contents[:len( + rif.contents) - len(last_line)] + last_line = rif.contents.splitlines(keepends=True)[-1] - segs = [code_before, code_after] - if segs[0].strip() == "": - segs[0] = segs[0].strip() - if segs[1].strip() == "": - segs[1] = segs[1].strip() + while rif.contents.startswith("\n"): + file_prefix += "\n" + rif.contents = rif.contents[1:] + while rif.contents.endswith("\n"): + file_suffix = "\n" + file_suffix + rif.contents = rif.contents[:-1] - # Move any surrounding blank line in rif.contents to the prefix/suffix - if len(rif.contents) > 0: - first_line = rif.contents.splitlines(keepends=True)[0] - while first_line.strip() == "": - segs[0] += first_line - rif.contents = rif.contents[len(first_line):] - first_line = rif.contents.splitlines(keepends=True)[0] + return file_prefix, rif.contents, file_suffix, model_to_use - last_line = rif.contents.splitlines(keepends=True)[-1] - while last_line.strip() == "": - segs[1] = last_line + segs[1] - rif.contents = rif.contents[:len( - rif.contents) - len(last_line)] - last_line = rif.contents.splitlines(keepends=True)[-1] - - while rif.contents.startswith("\n"): - segs[0] += "\n" - rif.contents = rif.contents[1:] - while rif.contents.endswith("\n"): - segs[1] = "\n" + segs[1] - rif.contents = rif.contents[:-1] - - # .format(code=rif.contents, user_request=self.user_input, file_prefix=segs[0], file_suffix=segs[1]) - prompt = self._prompt - if segs[0].strip() != "": - prompt += dedent(f""" + def compile_prompt(self, file_prefix: str, contents: str, file_suffix: str, sdk: ContinueSDK) -> str: + prompt = self._prompt + if file_prefix.strip() != "": + prompt += dedent(f""" -{segs[0]} +{file_prefix} """) - prompt += dedent(f""" + prompt += dedent(f""" -{rif.contents} +{contents} """) - if segs[1].strip() != "": - prompt += dedent(f""" + if file_suffix.strip() != "": + prompt += dedent(f""" -{segs[1]} +{file_suffix} """) - prompt += dedent(f""" + prompt += dedent(f""" {self.user_input} """) - lines = [] - unfinished_line = "" - i = 0 - original_lines = rif.contents.split("\n") - - async def add_line(i: int, line: str): - if i == 0: - # First line indentation, because the model will assume that it is replacing in this way - line = original_lines[0].replace( - original_lines[0].strip(), "") + line - - if i < len(original_lines): - # Replace original line - range = Range.from_shorthand( - rif.range.start.line + i, rif.range.start.character if i == 0 else 0, rif.range.start.line + i + 1, 0) - else: - # Insert a line - range = Range.from_shorthand( - rif.range.start.line + i, 0, rif.range.start.line + i, 0) - - await sdk.ide.applyFileSystemEdit(FileEdit( - filepath=rif.filepath, - range=range, - replacement=line + "\n" - )) - - lines_of_prefix_copied = 0 - line_below_highlighted_range = segs[1].lstrip().split("\n")[0] - should_stop = False - async for chunk in model_to_use.stream_chat(prompt, with_history=await sdk.get_chat_context(), temperature=0): - if should_stop: + return prompt + + def is_end_line(self, line: str) -> bool: + return "" in line + + def line_to_be_ignored(self, line: str) -> bool: + return "```" in line or "" in line or "" in line or "" in line or "" in line or "" in line or "" in line or "" in line or "" in line or "" in line + + async def stream_rif(self, rif: RangeInFileWithContents, sdk: ContinueSDK): + full_file_contents = await sdk.ide.readFile(rif.filepath) + + file_prefix, contents, file_suffix, model_to_use = await self.get_prompt_parts( + rif, sdk, full_file_contents) + prompt = self.compile_prompt(file_prefix, contents, file_suffix, sdk) + + full_file_contents_lines = full_file_contents.split("\n") + original_lines = rif.contents.split("\n") + i = 0 + lines = [] + unfinished_line = "" + + current_block = [] + offset_from_blocks = 0 + + async def insert_line(line: str, line_no: int): + nonlocal current_block + # Insert line, highlight green, highlight corresponding line red + range = Range.from_shorthand( + line_no, 0, line_no, 0) + red_range = Range.from_shorthand( + line_no + len(current_block), 0, line_no + len(current_block), 0) + + await sdk.ide.applyFileSystemEdit(FileEdit( + filepath=rif.filepath, + range=range, + replacement=line + "\n" + )) + await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=range), "#00FF0022") + await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=red_range), "#FF000022") + + async def show_block_as_suggestion(): + nonlocal i, offset_from_blocks, current_block + await sdk.ide.showSuggestion(FileEdit( + filepath=rif.filepath, + range=Range.from_shorthand( + i + offset_from_blocks - len(current_block) + rif.range.start.line, 0, i + offset_from_blocks + rif.range.start.line, 0), + replacement="\n".join(current_block) + "\n" + )) + offset_from_blocks += len(current_block) + current_block.clear() + + async def add_to_block(line: str): + current_block.append(line) + # TODO: This start line might have changed above + # await insert_line(line, i + offset_from_blocks + + # rif.range.start.line) + + async def handle_generated_line(line: str): + nonlocal i, lines, current_block, offset_from_blocks, original_lines + # diff = list(difflib.ndiff(rif.contents.splitlines( + # keepends=True), completion.splitlines(keepends=True))) + if i < len(original_lines) and line == original_lines[i]: + # Line is the same as the original. Start a new block + await show_block_as_suggestion() + else: + # Add to the current block + await add_to_block(line) + + lines_of_prefix_copied = 0 + repeating_file_suffix = False + line_below_highlighted_range = file_suffix.lstrip().split("\n")[0] + async for chunk in model_to_use.stream_chat(prompt, with_history=await sdk.get_chat_context(), temperature=0): + # Stop early if it is repeating the file_suffix + if repeating_file_suffix: + break + + # Accumulate lines + chunk_lines = chunk.split("\n") + chunk_lines[0] = unfinished_line + chunk_lines[0] + if chunk.endswith("\n"): + unfinished_line = "" + chunk_lines.pop() # because this will be an empty string + else: + unfinished_line = chunk_lines.pop() + lines.extend(chunk_lines) + + # Deal with newly accumulated lines + for line in chunk_lines: + # Lines that should signify the end of generation + if self.is_end_line(line): + break + # Lines that should be ignored, like the <> tags + elif self.line_to_be_ignored(line): + continue + # Check if we are currently just copying the prefix + elif (lines_of_prefix_copied > 0 or i == 0) and lines_of_prefix_copied < len(file_prefix.splitlines()) and line == full_file_contents_lines[lines_of_prefix_copied]: + # This is a sketchy way of stopping it from repeating the file_prefix. Is a bug if output happens to have a matching line + lines_of_prefix_copied += 1 + continue + # Because really short lines might be expected to be repeated, this is only a !heuristic! + # Stop when it starts copying the file_suffix + elif line.strip() == line_below_highlighted_range.strip() and len(line.strip()) > 4: + repeating_file_suffix = True break - chunk_lines = chunk.split("\n") - chunk_lines[0] = unfinished_line + chunk_lines[0] - if chunk.endswith("\n"): - unfinished_line = "" - chunk_lines.pop() # because this will be an empty string - else: - unfinished_line = chunk_lines.pop() - lines.extend(chunk_lines) - - for line in chunk_lines: - if "" in line: - break - elif "```" in line or "" in line or "" in line or "" in line or "" in line or "" in line or "" in line or "" in line or "" in line or "" in line: - continue - elif (lines_of_prefix_copied > 0 or i == 0) and lines_of_prefix_copied < len(segs[0].splitlines()) and line == full_file_contents_lst[lines_of_prefix_copied]: - # This is a sketchy way of stopping it from repeating the file_prefix. Is a bug if output happens to have a matching line - lines_of_prefix_copied += 1 - continue - elif i < len(original_lines) and line == original_lines[i]: - i += 1 - continue - # Because really short lines might be expected to be repeated !heuristic! - elif line.strip() == line_below_highlighted_range.strip() and len(line.strip()) > 4: - should_stop = True - break - await add_line(i, line) - i += 1 - - # Add the unfinished line - if unfinished_line != "": - unfinished_line = unfinished_line.replace( - "", "").replace("", "").replace("```", "").replace("", "").replace("", "").replace("", "").replace("", "").replace(" 0: + await show_block_as_suggestion() + + # Record the completion + completion = "\n".join(lines) + self._prompt_and_completion += prompt + completion + + async def run(self, sdk: ContinueSDK) -> Coroutine[Observation, None, None]: + self.description = f"`{self.user_input}`" + await sdk.update_ui() + + rif_with_contents = [] + for range_in_file in map(lambda x: RangeInFile( + filepath=x.filepath, + # Only consider the range line-by-line. Maybe later don't if it's only a single line. + range=x.range.to_full_lines() + ), self.range_in_files): + file_contents = await sdk.ide.readRangeInFile(range_in_file) + rif_with_contents.append( + RangeInFileWithContents.from_range_in_file(range_in_file, file_contents)) + + rif_dict = {} + for rif in rif_with_contents: + rif_dict[rif.filepath] = rif.contents + + for rif in rif_with_contents: + await sdk.ide.setFileOpen(rif.filepath) + await self.stream_rif(rif, sdk) + # await sdk.ide.saveFile(rif.filepath) class EditFileStep(Step): -- cgit v1.2.3-70-g09d2 From 8262dd66cefc39f28d75e35e4de389d124aca2c0 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Wed, 21 Jun 2023 22:20:01 -0700 Subject: suggestions...closer? --- continuedev/src/continuedev/steps/core/core.py | 77 +++++++++++++++++++++----- extension/package.json | 38 ++++++++++++- extension/src/continueIdeClient.ts | 9 +++ 3 files changed, 109 insertions(+), 15 deletions(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index eb6a00c6..1238dfea 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -271,14 +271,21 @@ class DefaultModelEditCodeStep(Step): current_block = [] offset_from_blocks = 0 + last_matched_line = 0 + matched_line = 0 + current_block_start_of_insertion = -1 + lines_covered_in_this_block = 0 + liness_deleted_in_this_block = 0 + lines_same_in_this_block = 0 async def insert_line(line: str, line_no: int): nonlocal current_block # Insert line, highlight green, highlight corresponding line red + red_line = line_no + len(current_block) + 1 range = Range.from_shorthand( line_no, 0, line_no, 0) red_range = Range.from_shorthand( - line_no + len(current_block), 0, line_no + len(current_block), 0) + red_line, 0, red_line, 0) await sdk.ide.applyFileSystemEdit(FileEdit( filepath=rif.filepath, @@ -289,32 +296,73 @@ class DefaultModelEditCodeStep(Step): await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=red_range), "#FF000022") async def show_block_as_suggestion(): - nonlocal i, offset_from_blocks, current_block + nonlocal i, offset_from_blocks, current_block, current_block_start_of_insertion, matched_line, last_matched_line, lines_covered_in_this_block, liness_deleted_in_this_block + end_line = offset_from_blocks + rif.range.start.line + matched_line + # Delete the green inserted lines, because they will be shown as part of the suggestion + await sdk.ide.applyFileSystemEdit(FileEdit( + filepath=rif.filepath, + range=Range.from_shorthand( + current_block_start_of_insertion, 0, current_block_start_of_insertion + len(current_block), 0), + replacement="" + )) + + lines_deleted_in_this_block = lines_covered_in_this_block - lines_same_in_this_block await sdk.ide.showSuggestion(FileEdit( filepath=rif.filepath, range=Range.from_shorthand( - i + offset_from_blocks - len(current_block) + rif.range.start.line, 0, i + offset_from_blocks + rif.range.start.line, 0), + end_line - lines_deleted_in_this_block, 0, end_line, 0), replacement="\n".join(current_block) + "\n" )) offset_from_blocks += len(current_block) current_block.clear() - async def add_to_block(line: str): + async def add_green_to_block(line: str): + # Keep track of where the first inserted line in this block came from + nonlocal current_block_start_of_insertion + if current_block_start_of_insertion < 0: + current_block_start_of_insertion = i + offset_from_blocks + rif.range.start.line + + # Insert the line, highlight green + await insert_line(line, i + offset_from_blocks + rif.range.start.line) current_block.append(line) - # TODO: This start line might have changed above - # await insert_line(line, i + offset_from_blocks + - # rif.range.start.line) - async def handle_generated_line(line: str): - nonlocal i, lines, current_block, offset_from_blocks, original_lines + def line_matches_something_in_original(line: str) -> int: + nonlocal offset_from_blocks, last_matched_line, matched_line, lines_covered_in_this_block # diff = list(difflib.ndiff(rif.contents.splitlines( # keepends=True), completion.splitlines(keepends=True))) - if i < len(original_lines) and line == original_lines[i]: - # Line is the same as the original. Start a new block - await show_block_as_suggestion() + # TODO: and line.strip() != ""? + for j in range(last_matched_line, len(original_lines)): + if line == original_lines[j]: + last_matched_line = matched_line + lines_covered_in_this_block = j - matched_line + matched_line = j + return j + return -1 + + async def handle_generated_line(line: str): + nonlocal i, lines, current_block, offset_from_blocks, original_lines, current_block_start_of_insertion, matched_line, lines_covered_in_this_block, lines_same_in_this_block + + # Highlight the line to show progress + await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=Range.from_shorthand( + i + rif.range.start.line, 0, i + rif.range.start.line, 0)), "#FFFFFF22") + + # Check if this line appears to correspond to something in the original + if line_matches_something_in_original(line) >= 0: + if len(current_block) > 0: + # Matches something, add all lines up to this as red in the old block, then show the block + await show_block_as_suggestion() + i -= 1 + # i -= (len(current_block) - + # (matched_line - last_matched_line)) + lines_covered_in_this_block = 0 + lines_same_in_this_block = 0 + + current_block_start_of_insertion = -1 + lines_same_in_this_block += 1 + else: - # Add to the current block - await add_to_block(line) + # No match, insert the line into the replacement but don't change the red highlighting + await add_green_to_block(line) lines_of_prefix_copied = 0 repeating_file_suffix = False @@ -372,6 +420,7 @@ class DefaultModelEditCodeStep(Step): # If the current block isn't empty, add that suggestion if len(current_block) > 0: + matched_line = rif.range.end.line - rif.range.start.line await show_block_as_suggestion() # Record the completion diff --git a/extension/package.json b/extension/package.json index 94a58ebd..a9b8660b 100644 --- a/extension/package.json +++ b/extension/package.json @@ -65,12 +65,48 @@ } } }, - "commands": [], + "commands": [ + { + "command": "continue.suggestionDown", + "category": "Continue", + "title": "Suggestion Down" + }, + { + "command": "continue.suggestionUp", + "category": "Continue", + "title": "Suggestion Up" + }, + { + "command": "continue.acceptSuggestion", + "category": "Continue", + "title": "Accept Suggestion" + }, + { + "command": "continue.rejectSuggestion", + "category": "Continue", + "title": "Reject Suggestion" + } + ], "keybindings": [ { "command": "continue.focusContinueInput", "mac": "cmd+k", "key": "ctrl+k" + }, + { + "command": "continue.suggestionDown", + "mac": "shift+ctrl+down", + "key": "shift+ctrl+down" + }, + { + "command": "continue.suggestionUp", + "mac": "shift+ctrl+up", + "key": "shift+ctrl+up" + }, + { + "command": "continue.acceptSuggestion", + "mac": "shift+ctrl+enter", + "key": "shift+ctrl+enter" } ], "menus": { diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index fbd00c6e..b1fcd6fb 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -163,6 +163,15 @@ class IdeProtocolClient { isWholeLine: true, }); editor.setDecorations(decorationType, [range]); + + const cursorDisposable = vscode.window.onDidChangeTextEditorSelection( + (event) => { + if (event.textEditor.document.uri.fsPath === rangeInFile.filepath) { + cursorDisposable.dispose(); + editor.setDecorations(decorationType, []); + } + } + ); } } -- cgit v1.2.3-70-g09d2 From 5e583f8300cbc174a8bafb31362f55b3b234d3d2 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Thu, 22 Jun 2023 09:34:22 -0700 Subject: committing before I make difflib update to stream --- continuedev/src/continuedev/steps/core/core.py | 66 ++++++++++++++++---------- extension/src/suggestions.ts | 62 ++++++++++++------------ 2 files changed, 72 insertions(+), 56 deletions(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 1238dfea..3c50f586 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -265,7 +265,9 @@ class DefaultModelEditCodeStep(Step): full_file_contents_lines = full_file_contents.split("\n") original_lines = rif.contents.split("\n") - i = 0 + completion_lines_covered = 0 + # In the actual file, as it is with blocks and such + current_line_in_file = rif.range.start.line lines = [] unfinished_line = "" @@ -296,7 +298,7 @@ class DefaultModelEditCodeStep(Step): await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=red_range), "#FF000022") async def show_block_as_suggestion(): - nonlocal i, offset_from_blocks, current_block, current_block_start_of_insertion, matched_line, last_matched_line, lines_covered_in_this_block, liness_deleted_in_this_block + nonlocal completion_lines_covered, offset_from_blocks, current_block, current_block_start_of_insertion, matched_line, last_matched_line, lines_covered_in_this_block, liness_deleted_in_this_block, current_line_in_file end_line = offset_from_blocks + rif.range.start.line + matched_line # Delete the green inserted lines, because they will be shown as part of the suggestion await sdk.ide.applyFileSystemEdit(FileEdit( @@ -310,9 +312,12 @@ class DefaultModelEditCodeStep(Step): await sdk.ide.showSuggestion(FileEdit( filepath=rif.filepath, range=Range.from_shorthand( - end_line - lines_deleted_in_this_block, 0, end_line, 0), + current_block_start_of_insertion, 0, end_line, 0), replacement="\n".join(current_block) + "\n" )) + + current_line_in_file = end_line + \ + len(current_block) + 1 # CURRENTLY TODO HERE NOTE offset_from_blocks += len(current_block) current_block.clear() @@ -320,46 +325,56 @@ class DefaultModelEditCodeStep(Step): # Keep track of where the first inserted line in this block came from nonlocal current_block_start_of_insertion if current_block_start_of_insertion < 0: - current_block_start_of_insertion = i + offset_from_blocks + rif.range.start.line + current_block_start_of_insertion = current_line_in_file # Insert the line, highlight green - await insert_line(line, i + offset_from_blocks + rif.range.start.line) + await insert_line(line, current_line_in_file) current_block.append(line) - def line_matches_something_in_original(line: str) -> int: + def line_matches_something_in_original(line: str) -> bool: nonlocal offset_from_blocks, last_matched_line, matched_line, lines_covered_in_this_block - # diff = list(difflib.ndiff(rif.contents.splitlines( - # keepends=True), completion.splitlines(keepends=True))) + diff = list(difflib.ndiff( + original_lines[matched_line:], current_block + [line])) + i = current_line_in_file + if diff[i][0] == " ": + last_matched_line = matched_line + matched_line = i + lines_covered_in_this_block = matched_line - last_matched_line + return True + elif diff[i][0] == "-": + last_matched_line = matched_line + matched_line = i + lines_covered_in_this_block = matched_line - last_matched_line + return True + elif diff[i][0] == "+": + return False + # TODO: and line.strip() != ""? - for j in range(last_matched_line, len(original_lines)): + for j in range(matched_line, len(original_lines)): if line == original_lines[j]: last_matched_line = matched_line - lines_covered_in_this_block = j - matched_line matched_line = j - return j - return -1 + lines_covered_in_this_block = matched_line - last_matched_line + return True + return False async def handle_generated_line(line: str): - nonlocal i, lines, current_block, offset_from_blocks, original_lines, current_block_start_of_insertion, matched_line, lines_covered_in_this_block, lines_same_in_this_block + nonlocal completion_lines_covered, lines, current_block, offset_from_blocks, original_lines, current_block_start_of_insertion, matched_line, lines_covered_in_this_block, lines_same_in_this_block, current_line_in_file, completion_lines_covered # Highlight the line to show progress await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=Range.from_shorthand( - i + rif.range.start.line, 0, i + rif.range.start.line, 0)), "#FFFFFF22") + current_line_in_file, 0, current_line_in_file, 0)), "#FFFFFF22") # Check if this line appears to correspond to something in the original - if line_matches_something_in_original(line) >= 0: + if line_matches_something_in_original(line): if len(current_block) > 0: # Matches something, add all lines up to this as red in the old block, then show the block await show_block_as_suggestion() - i -= 1 - # i -= (len(current_block) - - # (matched_line - last_matched_line)) - lines_covered_in_this_block = 0 + # Begin next block! lines_same_in_this_block = 0 - + lines_covered_in_this_block = 0 current_block_start_of_insertion = -1 lines_same_in_this_block += 1 - else: # No match, insert the line into the replacement but don't change the red highlighting await add_green_to_block(line) @@ -391,7 +406,7 @@ class DefaultModelEditCodeStep(Step): elif self.line_to_be_ignored(line): continue # Check if we are currently just copying the prefix - elif (lines_of_prefix_copied > 0 or i == 0) and lines_of_prefix_copied < len(file_prefix.splitlines()) and line == full_file_contents_lines[lines_of_prefix_copied]: + elif (lines_of_prefix_copied > 0 or completion_lines_covered == 0) and lines_of_prefix_copied < len(file_prefix.splitlines()) and line == full_file_contents_lines[lines_of_prefix_copied]: # This is a sketchy way of stopping it from repeating the file_prefix. Is a bug if output happens to have a matching line lines_of_prefix_copied += 1 continue @@ -403,16 +418,17 @@ class DefaultModelEditCodeStep(Step): # If none of the above, insert the line! await handle_generated_line(line) - i += 1 + completion_lines_covered += 1 + current_line_in_file += 1 # Add the unfinished line if unfinished_line != "" and not self.line_to_be_ignored(unfinished_line) and not self.is_end_line(unfinished_line): lines.append(unfinished_line) await handle_generated_line(unfinished_line) - i += 1 + completion_lines_covered += 1 # Highlight the remainder of the range red - if i < len(original_lines): + if completion_lines_covered < len(original_lines): await handle_generated_line("") # range = Range.from_shorthand( # i + 1 + offset_from_blocks + rif.range.start.line, 0, len(original_lines) + offset_from_blocks + rif.range.start.line, 0) diff --git a/extension/src/suggestions.ts b/extension/src/suggestions.ts index 5ac6e095..2e4e0ea2 100644 --- a/extension/src/suggestions.ts +++ b/extension/src/suggestions.ts @@ -218,42 +218,42 @@ export async function showSuggestion( range: vscode.Range, suggestion: string ): Promise { - const existingCode = await readFileAtRange( - new vscode.Range(range.start, range.end), - editorFilename - ); + // const existingCode = await readFileAtRange( + // new vscode.Range(range.start, range.end), + // editorFilename + // ); // If any of the outside lines are the same, don't repeat them in the suggestion - const slines = suggestion.split("\n"); - const elines = existingCode.split("\n"); - let linesRemovedBefore = 0; - let linesRemovedAfter = 0; - while (slines.length > 0 && elines.length > 0 && slines[0] === elines[0]) { - slines.shift(); - elines.shift(); - linesRemovedBefore++; - } + // const slines = suggestion.split("\n"); + // const elines = existingCode.split("\n"); + // let linesRemovedBefore = 0; + // let linesRemovedAfter = 0; + // while (slines.length > 0 && elines.length > 0 && slines[0] === elines[0]) { + // slines.shift(); + // elines.shift(); + // linesRemovedBefore++; + // } - while ( - slines.length > 0 && - elines.length > 0 && - slines[slines.length - 1] === elines[elines.length - 1] - ) { - slines.pop(); - elines.pop(); - linesRemovedAfter++; - } + // while ( + // slines.length > 0 && + // elines.length > 0 && + // slines[slines.length - 1] === elines[elines.length - 1] + // ) { + // slines.pop(); + // elines.pop(); + // linesRemovedAfter++; + // } - suggestion = slines.join("\n"); - if (suggestion === "") return Promise.resolve(false); // Don't even make a suggestion if they are exactly the same + // suggestion = slines.join("\n"); + // if (suggestion === "") return Promise.resolve(false); // Don't even make a suggestion if they are exactly the same - range = new vscode.Range( - new vscode.Position(range.start.line + linesRemovedBefore, 0), - new vscode.Position( - range.end.line - linesRemovedAfter, - elines.at(-1)?.length || 0 - ) - ); + // range = new vscode.Range( + // new vscode.Position(range.start.line + linesRemovedBefore, 0), + // new vscode.Position( + // range.end.line - linesRemovedAfter, + // elines.at(-1)?.length || 0 + // ) + // ); const editor = await openEditorAndRevealRange(editorFilename, range); if (!editor) return Promise.resolve(false); -- cgit v1.2.3-70-g09d2 From 0846a5dca6530a5cd6dad97952d2844a463a15e1 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Thu, 22 Jun 2023 12:51:07 -0700 Subject: starting to use diff to create blocks --- continuedev/src/continuedev/steps/core/core.py | 62 +++++++++++++++++++++----- 1 file changed, 50 insertions(+), 12 deletions(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 3c50f586..d4ccda58 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -271,7 +271,10 @@ class DefaultModelEditCodeStep(Step): lines = [] unfinished_line = "" - current_block = [] + current_block_added = [] + current_block_removed = [] + last_diff_char = " " + offset_from_blocks = 0 last_matched_line = 0 matched_line = 0 @@ -281,9 +284,9 @@ class DefaultModelEditCodeStep(Step): lines_same_in_this_block = 0 async def insert_line(line: str, line_no: int): - nonlocal current_block + nonlocal current_block_added # Insert line, highlight green, highlight corresponding line red - red_line = line_no + len(current_block) + 1 + red_line = line_no + len(current_block_added) + 1 range = Range.from_shorthand( line_no, 0, line_no, 0) red_range = Range.from_shorthand( @@ -298,7 +301,7 @@ class DefaultModelEditCodeStep(Step): await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=red_range), "#FF000022") async def show_block_as_suggestion(): - nonlocal completion_lines_covered, offset_from_blocks, current_block, current_block_start_of_insertion, matched_line, last_matched_line, lines_covered_in_this_block, liness_deleted_in_this_block, current_line_in_file + nonlocal completion_lines_covered, offset_from_blocks, current_block_added, current_block_removed, current_block_start_of_insertion, matched_line, last_matched_line, lines_covered_in_this_block, liness_deleted_in_this_block, current_line_in_file end_line = offset_from_blocks + rif.range.start.line + matched_line # Delete the green inserted lines, because they will be shown as part of the suggestion await sdk.ide.applyFileSystemEdit(FileEdit( @@ -333,8 +336,9 @@ class DefaultModelEditCodeStep(Step): def line_matches_something_in_original(line: str) -> bool: nonlocal offset_from_blocks, last_matched_line, matched_line, lines_covered_in_this_block - diff = list(difflib.ndiff( - original_lines[matched_line:], current_block + [line])) + diff = list(filter(lambda x: not x.startswith("?"), difflib.ndiff( + original_lines[matched_line:], current_block + [line]))) + i = current_line_in_file if diff[i][0] == " ": last_matched_line = matched_line @@ -358,16 +362,36 @@ class DefaultModelEditCodeStep(Step): return True return False + def block_not_empty() -> bool: + nonlocal current_block_added, current_block_removed + return len(current_block_added) or len(current_block_removed) + async def handle_generated_line(line: str): - nonlocal completion_lines_covered, lines, current_block, offset_from_blocks, original_lines, current_block_start_of_insertion, matched_line, lines_covered_in_this_block, lines_same_in_this_block, current_line_in_file, completion_lines_covered + nonlocal completion_lines_covered, lines, current_block_added, current_block_removed, offset_from_blocks, original_lines, current_block_start_of_insertion, matched_line, lines_covered_in_this_block, lines_same_in_this_block, current_line_in_file, completion_lines_covered, last_diff_char # Highlight the line to show progress await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=Range.from_shorthand( current_line_in_file, 0, current_line_in_file, 0)), "#FFFFFF22") - # Check if this line appears to correspond to something in the original - if line_matches_something_in_original(line): - if len(current_block) > 0: + # Get the diff of current block and the original + diff = list(filter(lambda x: not x.startswith("?"), difflib.ndiff( + original_lines[matched_line:], current_block_added + [line]))) + next_diff_char = diff[current_line_in_file][0] + + # If we need to start a new block, end the old one + if next_diff_char != last_diff_char: + await show_block_as_suggestion() + + if next_diff_char == " ": + if block_not_empty(): + await show_block_as_suggestion() + + current_block_start_of_insertion = -1 + lines_same_in_this_block += 1 + + elif next_diff_char == "-": + # Line was removed from the original, add it to the block + if block_not_empty(): # Matches something, add all lines up to this as red in the old block, then show the block await show_block_as_suggestion() # Begin next block! @@ -375,9 +399,23 @@ class DefaultModelEditCodeStep(Step): lines_covered_in_this_block = 0 current_block_start_of_insertion = -1 lines_same_in_this_block += 1 + elif next_diff_char == "+": + # Line was added to the original, add it to the block + + if block_not_empty(): + # Matches something, add all lines up to this as red in the old block, then show the block + await show_block_as_suggestion() + # Begin next block! + lines_same_in_this_block = 0 + lines_covered_in_this_block = 0 + current_block_start_of_insertion = -1 + lines_same_in_this_block += 1 + else: - # No match, insert the line into the replacement but don't change the red highlighting - await add_green_to_block(line) + raise Exception("Unexpected diff character: " + + diff[current_line_in_file][0]) + + last_diff_char = next_diff_char lines_of_prefix_copied = 0 repeating_file_suffix = False -- cgit v1.2.3-70-g09d2 From 99e065d720fa345d96e98468b8a0fc8a7971c83b Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Thu, 22 Jun 2023 13:04:49 -0700 Subject: more diff work, checkpoint --- continuedev/src/continuedev/steps/core/core.py | 40 +++++++++----------------- 1 file changed, 14 insertions(+), 26 deletions(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index d4ccda58..64f53c0f 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -271,6 +271,7 @@ class DefaultModelEditCodeStep(Step): lines = [] unfinished_line = "" + red_or_green_first = "green" current_block_added = [] current_block_removed = [] last_diff_char = " " @@ -362,9 +363,15 @@ class DefaultModelEditCodeStep(Step): return True return False - def block_not_empty() -> bool: - nonlocal current_block_added, current_block_removed - return len(current_block_added) or len(current_block_removed) + def should_end_current_block(next_diff_char: str) -> bool: + nonlocal current_block_added, current_block_removed, last_diff_char + if next_diff_char == " ": + return len(current_block_added) or len(current_block_removed) + elif next_diff_char == "-": + return last_diff_char == "+" and len(current_block_removed) + elif next_diff_char == "+": + return last_diff_char == "-" and len(current_block_added) + raise Exception("Invalid next_diff_char") async def handle_generated_line(line: str): nonlocal completion_lines_covered, lines, current_block_added, current_block_removed, offset_from_blocks, original_lines, current_block_start_of_insertion, matched_line, lines_covered_in_this_block, lines_same_in_this_block, current_line_in_file, completion_lines_covered, last_diff_char @@ -379,37 +386,18 @@ class DefaultModelEditCodeStep(Step): next_diff_char = diff[current_line_in_file][0] # If we need to start a new block, end the old one - if next_diff_char != last_diff_char: + if should_end_current_block(next_diff_char): await show_block_as_suggestion() - - if next_diff_char == " ": - if block_not_empty(): - await show_block_as_suggestion() - current_block_start_of_insertion = -1 lines_same_in_this_block += 1 elif next_diff_char == "-": # Line was removed from the original, add it to the block - if block_not_empty(): - # Matches something, add all lines up to this as red in the old block, then show the block - await show_block_as_suggestion() - # Begin next block! - lines_same_in_this_block = 0 - lines_covered_in_this_block = 0 - current_block_start_of_insertion = -1 - lines_same_in_this_block += 1 + await add_red_to_block(line) + elif next_diff_char == "+": # Line was added to the original, add it to the block - - if block_not_empty(): - # Matches something, add all lines up to this as red in the old block, then show the block - await show_block_as_suggestion() - # Begin next block! - lines_same_in_this_block = 0 - lines_covered_in_this_block = 0 - current_block_start_of_insertion = -1 - lines_same_in_this_block += 1 + await add_green_to_block(line) else: raise Exception("Unexpected diff character: " + -- cgit v1.2.3-70-g09d2 From d36b7b74351581c64a5c4a91949bef9cf611516f Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Sun, 25 Jun 2023 10:24:05 -0700 Subject: red/green updates --- continuedev/src/continuedev/steps/core/core.py | 83 ++++++++++++++------------ 1 file changed, 45 insertions(+), 38 deletions(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 64f53c0f..539a3990 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -2,7 +2,7 @@ import os import subprocess from textwrap import dedent -from typing import Coroutine, List, Union +from typing import Coroutine, List, Literal, Union from ...models.main import Range from ...libs.llm.prompt_utils import MarkdownStyleEncoderDecoder @@ -271,7 +271,7 @@ class DefaultModelEditCodeStep(Step): lines = [] unfinished_line = "" - red_or_green_first = "green" + red_or_green_first: Literal["green", "red"] = "green" current_block_added = [] current_block_removed = [] last_diff_char = " " @@ -284,46 +284,50 @@ class DefaultModelEditCodeStep(Step): liness_deleted_in_this_block = 0 lines_same_in_this_block = 0 - async def insert_line(line: str, line_no: int): - nonlocal current_block_added - # Insert line, highlight green, highlight corresponding line red - red_line = line_no + len(current_block_added) + 1 - range = Range.from_shorthand( - line_no, 0, line_no, 0) - red_range = Range.from_shorthand( - red_line, 0, red_line, 0) - - await sdk.ide.applyFileSystemEdit(FileEdit( - filepath=rif.filepath, - range=range, - replacement=line + "\n" - )) - await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=range), "#00FF0022") - await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=red_range), "#FF000022") + async def insert_line(line: str, line_no: int, color: Literal{"red", "green"}): + if color == "green": + range = Range.from_shorthand( + line_no, 0, line_no, 0) + + await sdk.ide.applyFileSystemEdit(FileEdit( + filepath=rif.filepath, + range=range, + replacement=line + "\n" + )) + + color = '#00FF0022' if color == "green" else "#FF000022" + await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=range), color) async def show_block_as_suggestion(): nonlocal completion_lines_covered, offset_from_blocks, current_block_added, current_block_removed, current_block_start_of_insertion, matched_line, last_matched_line, lines_covered_in_this_block, liness_deleted_in_this_block, current_line_in_file end_line = offset_from_blocks + rif.range.start.line + matched_line - # Delete the green inserted lines, because they will be shown as part of the suggestion - await sdk.ide.applyFileSystemEdit(FileEdit( - filepath=rif.filepath, - range=Range.from_shorthand( - current_block_start_of_insertion, 0, current_block_start_of_insertion + len(current_block), 0), - replacement="" - )) - - lines_deleted_in_this_block = lines_covered_in_this_block - lines_same_in_this_block - await sdk.ide.showSuggestion(FileEdit( - filepath=rif.filepath, - range=Range.from_shorthand( - current_block_start_of_insertion, 0, end_line, 0), - replacement="\n".join(current_block) + "\n" - )) - - current_line_in_file = end_line + \ - len(current_block) + 1 # CURRENTLY TODO HERE NOTE - offset_from_blocks += len(current_block) - current_block.clear() + + if red_or_green_first == "green": + # Delete the green inserted lines, because they will be shown as part of the suggestion + await sdk.ide.applyFileSystemEdit(FileEdit( + filepath=rif.filepath, + range=Range.from_shorthand( + current_block_start_of_insertion, 0, current_block_start_of_insertion + len(current_block), 0), + replacement="" + )) + + lines_deleted_in_this_block = lines_covered_in_this_block - lines_same_in_this_block + await sdk.ide.showSuggestion(FileEdit( + filepath=rif.filepath, + range=Range.from_shorthand( + current_block_start_of_insertion, 0, end_line, 0), + replacement="\n".join(current_block) + "\n" + )) + current_line_in_file = end_line + \ + len(current_block) + 1 # CURRENTLY TODO HERE NOTE + offset_from_blocks += len(current_block) + current_block.clear() + else: + # Ends in green, so if you want to delete the lines before the matched line, you need to start a new block. + current_block = [ + line for line in original_lines[] + ] + async def add_green_to_block(line: str): # Keep track of where the first inserted line in this block came from @@ -335,6 +339,9 @@ class DefaultModelEditCodeStep(Step): await insert_line(line, current_line_in_file) current_block.append(line) + async def add_red_to_block(line: str): + await insert_line() + def line_matches_something_in_original(line: str) -> bool: nonlocal offset_from_blocks, last_matched_line, matched_line, lines_covered_in_this_block diff = list(filter(lambda x: not x.startswith("?"), difflib.ndiff( -- cgit v1.2.3-70-g09d2 From 035a7cddec9bd26f834bc1c4fadd2cefdbb7b6dd Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Sun, 25 Jun 2023 20:54:40 -0700 Subject: more streaming --- continuedev/src/continuedev/steps/core/core.py | 47 ++++++++++++++++---------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 539a3990..1ca08951 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -284,7 +284,7 @@ class DefaultModelEditCodeStep(Step): liness_deleted_in_this_block = 0 lines_same_in_this_block = 0 - async def insert_line(line: str, line_no: int, color: Literal{"red", "green"}): + async def insert_line(line: str, line_no: int, color: Literal["red", "green"]): if color == "green": range = Range.from_shorthand( line_no, 0, line_no, 0) @@ -307,7 +307,7 @@ class DefaultModelEditCodeStep(Step): await sdk.ide.applyFileSystemEdit(FileEdit( filepath=rif.filepath, range=Range.from_shorthand( - current_block_start_of_insertion, 0, current_block_start_of_insertion + len(current_block), 0), + current_block_start_of_insertion, 0, current_block_start_of_insertion + len(current_block_added), 0), replacement="" )) @@ -316,36 +316,45 @@ class DefaultModelEditCodeStep(Step): filepath=rif.filepath, range=Range.from_shorthand( current_block_start_of_insertion, 0, end_line, 0), - replacement="\n".join(current_block) + "\n" + replacement="\n".join(current_block_added) + "\n" )) - current_line_in_file = end_line + \ - len(current_block) + 1 # CURRENTLY TODO HERE NOTE - offset_from_blocks += len(current_block) - current_block.clear() else: # Ends in green, so if you want to delete the lines before the matched line, you need to start a new block. - current_block = [ - line for line in original_lines[] - ] + pass + # current_block = [ + # line for line in original_lines[] + # ] + current_line_in_file = end_line + \ + len(current_block_added) + 1 # CURRENTLY TODO HERE NOTE + offset_from_blocks += len(current_block_added) + current_block_added.clear() + current_block_removed.clear() async def add_green_to_block(line: str): # Keep track of where the first inserted line in this block came from - nonlocal current_block_start_of_insertion + nonlocal current_block_start_of_insertion, current_block_added if current_block_start_of_insertion < 0: current_block_start_of_insertion = current_line_in_file # Insert the line, highlight green - await insert_line(line, current_line_in_file) - current_block.append(line) + await insert_line(line, current_line_in_file, "green") + current_block_added.append(line) + range = Range.from_shorthand( + current_line_in_file, 0, current_line_in_file, 0) + await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=range), "#00FF0022") async def add_red_to_block(line: str): - await insert_line() + # Highlight the current line red and insert + current_block_removed.append(line) + range = Range.from_shorthand( + current_line_in_file, 0, current_line_in_file, 0) + await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=range), "#FF000022") def line_matches_something_in_original(line: str) -> bool: nonlocal offset_from_blocks, last_matched_line, matched_line, lines_covered_in_this_block diff = list(filter(lambda x: not x.startswith("?"), difflib.ndiff( - original_lines[matched_line:], current_block + [line]))) + original_lines[matched_line:], current_block_added + [line]))) i = current_line_in_file if diff[i][0] == " ": @@ -389,7 +398,7 @@ class DefaultModelEditCodeStep(Step): # Get the diff of current block and the original diff = list(filter(lambda x: not x.startswith("?"), difflib.ndiff( - original_lines[matched_line:], current_block_added + [line]))) + original_lines, lines + [line]))) next_diff_char = diff[current_line_in_file][0] # If we need to start a new block, end the old one @@ -406,6 +415,10 @@ class DefaultModelEditCodeStep(Step): # Line was added to the original, add it to the block await add_green_to_block(line) + elif next_diff_char == " ": + # Line was unchanged, and didn't have to end a block + pass + else: raise Exception("Unexpected diff character: " + diff[current_line_in_file][0]) @@ -468,7 +481,7 @@ class DefaultModelEditCodeStep(Step): # await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=range), "#FF000022") # If the current block isn't empty, add that suggestion - if len(current_block) > 0: + if len(current_block_added) > 0 or len(current_block_removed) > 0: matched_line = rif.range.end.line - rif.range.start.line await show_block_as_suggestion() -- cgit v1.2.3-70-g09d2 From 3ecd29eb6031be378d8c8f01a1e25259e04087e5 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 27 Jun 2023 00:20:56 -0700 Subject: checkpoint on new streaming --- .../src/continuedev/libs/llm/proxy_server.py | 4 +- continuedev/src/continuedev/steps/core/core.py | 216 ++++++--------------- extension/src/activation/environmentSetup.ts | 6 +- extension/src/continueIdeClient.ts | 6 + extension/src/lang-server/codeLens.ts | 4 +- extension/src/suggestions.ts | 52 +++-- 6 files changed, 106 insertions(+), 182 deletions(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/libs/llm/proxy_server.py b/continuedev/src/continuedev/libs/llm/proxy_server.py index a29f5c89..78219695 100644 --- a/continuedev/src/continuedev/libs/llm/proxy_server.py +++ b/continuedev/src/continuedev/libs/llm/proxy_server.py @@ -71,7 +71,7 @@ class ProxyServer(LLM): async def complete(self, prompt: str, with_history: List[ChatMessage] = [], **kwargs) -> Coroutine[Any, Any, str]: async with aiohttp.ClientSession() as session: async with session.post(f"{SERVER_URL}/complete", json={ - "chat_history": self.compile_chat_messages(with_history, prompt), + "messages": self.compile_chat_messages(with_history, prompt), "model": self.default_model, "unique_id": self.unique_id, }) as resp: @@ -83,7 +83,7 @@ class ProxyServer(LLM): async def stream_chat(self, prompt, with_history: List[ChatMessage] = [], **kwargs) -> Generator[Union[Any, List, Dict], None, None]: async with aiohttp.ClientSession() as session: async with session.post(f"{SERVER_URL}/stream_complete", json={ - "chat_history": self.compile_chat_messages(with_history, prompt), + "messages": self.compile_chat_messages(with_history, prompt), "model": self.default_model, "unique_id": self.unique_id, }) as resp: diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 1ca08951..7a62220b 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -268,166 +268,61 @@ class DefaultModelEditCodeStep(Step): completion_lines_covered = 0 # In the actual file, as it is with blocks and such current_line_in_file = rif.range.start.line - lines = [] - unfinished_line = "" - - red_or_green_first: Literal["green", "red"] = "green" - current_block_added = [] - current_block_removed = [] - last_diff_char = " " + current_block_lines = [] + original_lines_below_previous_blocks = original_lines + current_block_start = -1 offset_from_blocks = 0 - last_matched_line = 0 - matched_line = 0 - current_block_start_of_insertion = -1 - lines_covered_in_this_block = 0 - liness_deleted_in_this_block = 0 - lines_same_in_this_block = 0 - - async def insert_line(line: str, line_no: int, color: Literal["red", "green"]): - if color == "green": - range = Range.from_shorthand( - line_no, 0, line_no, 0) - - await sdk.ide.applyFileSystemEdit(FileEdit( - filepath=rif.filepath, - range=range, - replacement=line + "\n" - )) - - color = '#00FF0022' if color == "green" else "#FF000022" - await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=range), color) - - async def show_block_as_suggestion(): - nonlocal completion_lines_covered, offset_from_blocks, current_block_added, current_block_removed, current_block_start_of_insertion, matched_line, last_matched_line, lines_covered_in_this_block, liness_deleted_in_this_block, current_line_in_file - end_line = offset_from_blocks + rif.range.start.line + matched_line - - if red_or_green_first == "green": - # Delete the green inserted lines, because they will be shown as part of the suggestion - await sdk.ide.applyFileSystemEdit(FileEdit( - filepath=rif.filepath, - range=Range.from_shorthand( - current_block_start_of_insertion, 0, current_block_start_of_insertion + len(current_block_added), 0), - replacement="" - )) - - lines_deleted_in_this_block = lines_covered_in_this_block - lines_same_in_this_block - await sdk.ide.showSuggestion(FileEdit( - filepath=rif.filepath, - range=Range.from_shorthand( - current_block_start_of_insertion, 0, end_line, 0), - replacement="\n".join(current_block_added) + "\n" - )) - else: - # Ends in green, so if you want to delete the lines before the matched line, you need to start a new block. - pass - # current_block = [ - # line for line in original_lines[] - # ] - - current_line_in_file = end_line + \ - len(current_block_added) + 1 # CURRENTLY TODO HERE NOTE - offset_from_blocks += len(current_block_added) - current_block_added.clear() - current_block_removed.clear() - - async def add_green_to_block(line: str): - # Keep track of where the first inserted line in this block came from - nonlocal current_block_start_of_insertion, current_block_added - if current_block_start_of_insertion < 0: - current_block_start_of_insertion = current_line_in_file - - # Insert the line, highlight green - await insert_line(line, current_line_in_file, "green") - current_block_added.append(line) - range = Range.from_shorthand( - current_line_in_file, 0, current_line_in_file, 0) - await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=range), "#00FF0022") - - async def add_red_to_block(line: str): - # Highlight the current line red and insert - current_block_removed.append(line) - range = Range.from_shorthand( - current_line_in_file, 0, current_line_in_file, 0) - await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=range), "#FF000022") - - def line_matches_something_in_original(line: str) -> bool: - nonlocal offset_from_blocks, last_matched_line, matched_line, lines_covered_in_this_block - diff = list(filter(lambda x: not x.startswith("?"), difflib.ndiff( - original_lines[matched_line:], current_block_added + [line]))) - - i = current_line_in_file - if diff[i][0] == " ": - last_matched_line = matched_line - matched_line = i - lines_covered_in_this_block = matched_line - last_matched_line - return True - elif diff[i][0] == "-": - last_matched_line = matched_line - matched_line = i - lines_covered_in_this_block = matched_line - last_matched_line - return True - elif diff[i][0] == "+": - return False - - # TODO: and line.strip() != ""? - for j in range(matched_line, len(original_lines)): - if line == original_lines[j]: - last_matched_line = matched_line - matched_line = j - lines_covered_in_this_block = matched_line - last_matched_line - return True - return False - - def should_end_current_block(next_diff_char: str) -> bool: - nonlocal current_block_added, current_block_removed, last_diff_char - if next_diff_char == " ": - return len(current_block_added) or len(current_block_removed) - elif next_diff_char == "-": - return last_diff_char == "+" and len(current_block_removed) - elif next_diff_char == "+": - return last_diff_char == "-" and len(current_block_added) - raise Exception("Invalid next_diff_char") + + lines_of_prefix_copied = 0 + repeating_file_suffix = False + line_below_highlighted_range = file_suffix.lstrip().split("\n")[0] + lines = [] + unfinished_line = "" async def handle_generated_line(line: str): - nonlocal completion_lines_covered, lines, current_block_added, current_block_removed, offset_from_blocks, original_lines, current_block_start_of_insertion, matched_line, lines_covered_in_this_block, lines_same_in_this_block, current_line_in_file, completion_lines_covered, last_diff_char + nonlocal lines, current_block_start, current_line_in_file, original_lines, original_lines_below_previous_blocks, current_block_lines, offset_from_blocks # Highlight the line to show progress await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=Range.from_shorthand( - current_line_in_file, 0, current_line_in_file, 0)), "#FFFFFF22") - - # Get the diff of current block and the original - diff = list(filter(lambda x: not x.startswith("?"), difflib.ndiff( - original_lines, lines + [line]))) - next_diff_char = diff[current_line_in_file][0] + current_line_in_file, 0, current_line_in_file, 0)), "#FFFFFF22" if len(current_block_lines) == 0 else "#FFFF0022") + + if len(current_block_lines) == 0: + if len(original_lines_below_previous_blocks) == 0 or line != original_lines_below_previous_blocks[0]: + current_block_lines.append(line) + current_block_start = current_line_in_file + + else: + original_lines_below_previous_blocks = original_lines_below_previous_blocks[ + 1:] + return + + # We are in a block currently, and checking for whether it should be ended + for i in range(len(original_lines_below_previous_blocks)): + og_line = original_lines_below_previous_blocks[i] + if og_line == line and len(og_line.strip()): + # Gather the lines to insert/replace for the suggestion + lines_to_replace = current_block_lines[:i] + original_lines_below_previous_blocks = original_lines_below_previous_blocks[ + i + 1:] + + # Insert the suggestion + await sdk.ide.showSuggestion(FileEdit( + filepath=rif.filepath, + range=Range.from_shorthand( + current_block_start, 0, current_block_start + i, 0), + replacement="\n".join(current_block_lines) + )) + + # Reset current block + offset_from_blocks += len(current_block_lines) + current_line_in_file += len(current_block_lines) + current_block_lines = [] + current_block_start = -1 + return + + current_block_lines.append(line) - # If we need to start a new block, end the old one - if should_end_current_block(next_diff_char): - await show_block_as_suggestion() - current_block_start_of_insertion = -1 - lines_same_in_this_block += 1 - - elif next_diff_char == "-": - # Line was removed from the original, add it to the block - await add_red_to_block(line) - - elif next_diff_char == "+": - # Line was added to the original, add it to the block - await add_green_to_block(line) - - elif next_diff_char == " ": - # Line was unchanged, and didn't have to end a block - pass - - else: - raise Exception("Unexpected diff character: " + - diff[current_line_in_file][0]) - - last_diff_char = next_diff_char - - lines_of_prefix_copied = 0 - repeating_file_suffix = False - line_below_highlighted_range = file_suffix.lstrip().split("\n")[0] async for chunk in model_to_use.stream_chat(prompt, with_history=await sdk.get_chat_context(), temperature=0): # Stop early if it is repeating the file_suffix if repeating_file_suffix: @@ -473,17 +368,14 @@ class DefaultModelEditCodeStep(Step): await handle_generated_line(unfinished_line) completion_lines_covered += 1 - # Highlight the remainder of the range red - if completion_lines_covered < len(original_lines): - await handle_generated_line("") - # range = Range.from_shorthand( - # i + 1 + offset_from_blocks + rif.range.start.line, 0, len(original_lines) + offset_from_blocks + rif.range.start.line, 0) - # await sdk.ide.highlightCode(RangeInFile(filepath=rif.filepath, range=range), "#FF000022") - # If the current block isn't empty, add that suggestion - if len(current_block_added) > 0 or len(current_block_removed) > 0: - matched_line = rif.range.end.line - rif.range.start.line - await show_block_as_suggestion() + if len(current_block_lines) > 0: + 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/src/activation/environmentSetup.ts b/extension/src/activation/environmentSetup.ts index 593b727e..cdaf3ac0 100644 --- a/extension/src/activation/environmentSetup.ts +++ b/extension/src/activation/environmentSetup.ts @@ -121,7 +121,7 @@ async function setupPythonEnv() { activateCmd, pipUpgradeCmd, `${pipCmd} install -r requirements.txt`, - ].join(" && "); + ].join(" ; "); const [, stderr] = await runCommand(installRequirementsCommand); if (stderr) { throw new Error(stderr); @@ -255,10 +255,10 @@ export async function downloadPython3() { throw new Error("python3 not found"); } else if (os === "linux") { command = - "sudo apt update && upgrade && sudo apt install python3 python3-pip"; + "sudo apt update ; upgrade ; sudo apt install python3 python3-pip"; } else if (os === "win32") { command = - "wget -O python_installer.exe https://www.python.org/ftp/python/3.11.3/python-3.11.3-amd64.exe && python_installer.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0"; + "wget -O python_installer.exe https://www.python.org/ftp/python/3.11.3/python-3.11.3-amd64.exe ; python_installer.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0"; pythonCmd = "python"; } diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index b1fcd6fb..877d9f3e 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -145,6 +145,7 @@ class IdeProtocolClient { // ------------------------------------ // // On message handlers + private _lastDecorationType: vscode.TextEditorDecorationType | null = null; async highlightCode(rangeInFile: RangeInFile, color: string) { const range = new vscode.Range( rangeInFile.range.start.line, @@ -172,6 +173,11 @@ class IdeProtocolClient { } } ); + + if (this._lastDecorationType) { + editor.setDecorations(this._lastDecorationType, []); + } + this._lastDecorationType = decorationType; } } diff --git a/extension/src/lang-server/codeLens.ts b/extension/src/lang-server/codeLens.ts index e8766c3c..3979b64d 100644 --- a/extension/src/lang-server/codeLens.ts +++ b/extension/src/lang-server/codeLens.ts @@ -20,12 +20,12 @@ class SuggestionsCodeLensProvider implements vscode.CodeLensProvider { ); codeLenses.push( new vscode.CodeLens(range, { - title: "Accept", + title: "Accept ✅", command: "continue.acceptSuggestion", arguments: [suggestion], }), new vscode.CodeLens(range, { - title: "Reject", + title: "Reject ❌", command: "continue.rejectSuggestion", arguments: [suggestion], }) diff --git a/extension/src/suggestions.ts b/extension/src/suggestions.ts index 2e4e0ea2..9b358899 100644 --- a/extension/src/suggestions.ts +++ b/extension/src/suggestions.ts @@ -59,10 +59,35 @@ export function rerenderDecorations(editorUri: string) { ); if (!suggestions || !editor) return; - const olds: vscode.Range[] = []; - const news: vscode.Range[] = []; - const oldSels: vscode.Range[] = []; - const newSels: vscode.Range[] = []; + const rangesWithoutEmptyLastLine = (ranges: vscode.Range[]) => { + const newRanges: vscode.Range[] = []; + for (let i = 0; i < ranges.length; i++) { + const range = ranges[i]; + if ( + range.start.line === range.end.line && + range.start.character === 0 && + range.end.character === 0 + ) { + // Empty range, don't show it + continue; + } + newRanges.push( + new vscode.Range( + range.start.line, + range.start.character, + // Don't include the last line if it is empty + range.end.line - (range.end.character === 0 ? 1 : 0), + range.end.character + ) + ); + } + return newRanges; + }; + + let olds: vscode.Range[] = []; + let news: vscode.Range[] = []; + let oldSels: vscode.Range[] = []; + let newSels: vscode.Range[] = []; for (let i = 0; i < suggestions.length; i++) { const suggestion = suggestions[i]; if (typeof idx != "undefined" && idx === i) { @@ -78,6 +103,13 @@ export function rerenderDecorations(editorUri: string) { news.push(suggestion.newRange); } } + + // Don't highlight the last line if it is empty + olds = rangesWithoutEmptyLastLine(olds); + news = rangesWithoutEmptyLastLine(news); + oldSels = rangesWithoutEmptyLastLine(oldSels); + newSels = rangesWithoutEmptyLastLine(newSels); + editor.setDecorations(oldDecorationType, olds); editor.setDecorations(newDecorationType, news); editor.setDecorations(oldSelDecorationType, oldSels); @@ -174,7 +206,7 @@ function selectSuggestion( rangeToDelete = new vscode.Range( rangeToDelete.start, - new vscode.Position(rangeToDelete.end.line + 1, 0) + new vscode.Position(rangeToDelete.end.line, 0) ); editor.edit((edit) => { edit.delete(rangeToDelete); @@ -261,19 +293,13 @@ export async function showSuggestion( return new Promise((resolve, reject) => { editor! .edit((edit) => { - if (range.end.line + 1 >= editor.document.lineCount) { - suggestion = "\n" + suggestion; - } - edit.insert( - new vscode.Position(range.end.line + 1, 0), - suggestion + "\n" - ); + edit.insert(new vscode.Position(range.end.line, 0), suggestion + "\n"); }) .then( (success) => { if (success) { let suggestionRange = new vscode.Range( - new vscode.Position(range.end.line + 1, 0), + new vscode.Position(range.end.line, 0), new vscode.Position( range.end.line + suggestion.split("\n").length, 0 -- cgit v1.2.3-70-g09d2 From 3d12cc4ac269f90dfe50eef2830887bff6719a33 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 27 Jun 2023 10:42:11 -0700 Subject: checkpoint - working well --- continuedev/src/continuedev/steps/core/core.py | 1 - 1 file changed, 1 deletion(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index 7a62220b..ae58cc99 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -316,7 +316,6 @@ class DefaultModelEditCodeStep(Step): # Reset current block offset_from_blocks += len(current_block_lines) - current_line_in_file += len(current_block_lines) current_block_lines = [] current_block_start = -1 return -- cgit v1.2.3-70-g09d2 From bedd5f31e7a1d7b915fbb2a47a92f58035c96415 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 27 Jun 2023 11:03:44 -0700 Subject: stop completion early, accept all improvements --- continuedev/src/continuedev/core/autopilot.py | 2 +- continuedev/src/continuedev/core/sdk.py | 3 +++ continuedev/src/continuedev/steps/core/core.py | 4 +++- extension/src/lang-server/codeLens.ts | 4 ++++ extension/src/suggestions.ts | 2 +- 5 files changed, 12 insertions(+), 3 deletions(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index a6e688ae..17eb70b3 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -121,7 +121,7 @@ class Autopilot(ContinueBaseModel): # If a parent step is deleted/cancelled, don't run this step last_depth = self._step_depth i = self.history.current_index - while i >= 0 and self.history.timeline[i].depth == last_depth + 1: + while i >= 0 and self.history.timeline[i].depth == last_depth - 1: if self.history.timeline[i].deleted: return None last_depth = self.history.timeline[i].depth diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py index d6acc404..8b82aee0 100644 --- a/continuedev/src/continuedev/core/sdk.py +++ b/continuedev/src/continuedev/core/sdk.py @@ -207,3 +207,6 @@ class ContinueSDK(AbstractContinueSDK): async def clear_history(self): await self.__autopilot.clear_history() + + def current_step_was_deleted(self): + return self.history.timeline[self.history.current_index].deleted diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index ae58cc99..4ec8fe9e 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -323,9 +323,11 @@ class DefaultModelEditCodeStep(Step): current_block_lines.append(line) async for chunk in model_to_use.stream_chat(prompt, with_history=await sdk.get_chat_context(), temperature=0): - # Stop early if it is repeating the file_suffix + # Stop early if it is repeating the file_suffix or the step was deleted if repeating_file_suffix: break + if sdk.current_step_was_deleted(): + return # Accumulate lines chunk_lines = chunk.split("\n") diff --git a/extension/src/lang-server/codeLens.ts b/extension/src/lang-server/codeLens.ts index 3979b64d..629da0b8 100644 --- a/extension/src/lang-server/codeLens.ts +++ b/extension/src/lang-server/codeLens.ts @@ -28,6 +28,10 @@ class SuggestionsCodeLensProvider implements vscode.CodeLensProvider { title: "Reject ❌", command: "continue.rejectSuggestion", arguments: [suggestion], + }), + new vscode.CodeLens(range, { + title: "(⌘⇧↩/⌘⇧⌫ to accept/reject all)", + command: "", }) ); } diff --git a/extension/src/suggestions.ts b/extension/src/suggestions.ts index 4631c33e..209bf8b2 100644 --- a/extension/src/suggestions.ts +++ b/extension/src/suggestions.ts @@ -246,7 +246,7 @@ function handleAllSuggestions(accept: boolean) { if (!suggestions) return; while (suggestions.length > 0) { - selectSuggestion(accept ? "new" : "old"); + selectSuggestion(accept ? "new" : "old", suggestions[0]); } } -- cgit v1.2.3-70-g09d2 From bf998a752a547485189f5ac1dc415d7ec475099e Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 27 Jun 2023 11:42:09 -0700 Subject: post-merge fixes --- continuedev/src/continuedev/steps/chat.py | 8 ++++++-- continuedev/src/continuedev/steps/core/core.py | 13 +++++++++++-- extension/src/activation/activate.ts | 15 +++++++++++++-- 3 files changed, 30 insertions(+), 6 deletions(-) (limited to 'continuedev') diff --git a/continuedev/src/continuedev/steps/chat.py b/continuedev/src/continuedev/steps/chat.py index 54d9c657..50e0f905 100644 --- a/continuedev/src/continuedev/steps/chat.py +++ b/continuedev/src/continuedev/steps/chat.py @@ -47,9 +47,13 @@ class AddFileStep(Step): except FileNotFoundError: self.description = f"File {self.filename} does not exist." return - currently_open_file = (await sdk.ide.getOpenFiles())[0] + await sdk.ide.setFileOpen(os.path.join(sdk.ide.workspace_directory, self.filename)) - await sdk.ide.setFileOpen(currently_open_file) + + open_files = await sdk.ide.getOpenFiles() + if len(open_files) > 0: + currently_open_file = (await sdk.ide.getOpenFiles())[0] + await sdk.ide.setFileOpen(currently_open_file) class DeleteFileStep(Step): diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index a487a1b5..9545e9c7 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -9,7 +9,7 @@ from ...libs.llm.prompt_utils import MarkdownStyleEncoderDecoder from ...models.filesystem_edit import EditDiff, FileEdit, FileEditWithFullContents, FileSystemEdit from ...models.filesystem import FileSystem, RangeInFile, RangeInFileWithContents from ...core.observation import Observation, TextObservation, TracebackObservation, UserInputObservation -from ...core.main import Step, SequentialStep +from ...core.main import ChatMessage, Step, SequentialStep from ...libs.util.count_tokens import MAX_TOKENS_FOR_MODEL, DEFAULT_MAX_TOKENS import difflib @@ -322,7 +322,13 @@ class DefaultModelEditCodeStep(Step): current_block_lines.append(line) - async for chunk in model_to_use.stream_chat(prompt, with_history=await sdk.get_chat_context(), temperature=0): + messages = await sdk.get_chat_context() + messages.append(ChatMessage( + role="user", + content=prompt, + summary=self.user_input + )) + async for chunk in model_to_use.stream_chat(messages, temperature=0): # Stop early if it is repeating the file_suffix or the step was deleted if repeating_file_suffix: break @@ -330,6 +336,9 @@ class DefaultModelEditCodeStep(Step): return # Accumulate lines + if "content" not in chunk: + continue + chunk = chunk["content"] chunk_lines = chunk.split("\n") chunk_lines[0] = unfinished_line + chunk_lines[0] if chunk.endswith("\n"): diff --git a/extension/src/activation/activate.ts b/extension/src/activation/activate.ts index 0c92f095..df8b6871 100644 --- a/extension/src/activation/activate.ts +++ b/extension/src/activation/activate.ts @@ -24,8 +24,19 @@ export async function activateExtension( registerAllCodeLensProviders(context); registerAllCommands(context); - // vscode.window.registerWebviewViewProvider("continue.continueGUIView", setupDebugPanel); - await startContinuePythonServer(); + await new Promise((resolve, reject) => { + vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: "Starting Continue Server...", + cancellable: false, + }, + async (progress, token) => { + await startContinuePythonServer(); + resolve(null); + } + ); + }); const serverUrl = getContinueServerUrl(); ideProtocolClient = new IdeProtocolClient( -- cgit v1.2.3-70-g09d2