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 --- extension/src/continueIdeClient.ts | 25 ++++++--------- extension/src/lang-server/codeLens.ts | 19 +++++------ extension/src/suggestions.ts | 60 +++++++++++++++++------------------ extension/src/util/vscode.ts | 20 ++++++------ 4 files changed, 60 insertions(+), 64 deletions(-) (limited to 'extension') diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index fbad5f5d..fbd00c6e 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -1,5 +1,8 @@ // import { ShowSuggestionRequest } from "../schema/ShowSuggestionRequest"; -import { showSuggestion, SuggestionRanges } from "./suggestions"; +import { + showSuggestion as showSuggestionInEditor, + SuggestionRanges, +} from "./suggestions"; import { openEditorAndRevealRange, getRightViewColumn } from "./util/vscode"; import { FileEdit } from "../schema/FileEdit"; import { RangeInFile } from "../schema/RangeInFile"; @@ -115,7 +118,10 @@ class IdeProtocolClient { break; case "setFileOpen": this.openFile(data.filepath); - // TODO: Close file + // TODO: Close file if False + break; + case "showSuggestion": + this.showSuggestion(data.edit); break; case "openGUI": case "connected": @@ -157,25 +163,12 @@ class IdeProtocolClient { isWholeLine: true, }); editor.setDecorations(decorationType, [range]); - - // Listen for changes to cursor position and then remove the decoration (but keep for at least 2 seconds) - const allowRemoveHighlight = () => { - const cursorDisposable = vscode.window.onDidChangeTextEditorSelection( - (event) => { - if (event.textEditor.document.uri.fsPath === rangeInFile.filepath) { - cursorDisposable.dispose(); - editor.setDecorations(decorationType, []); - } - } - ); - }; - setTimeout(allowRemoveHighlight, 2000); } } showSuggestion(edit: FileEdit) { // showSuggestion already exists - showSuggestion( + showSuggestionInEditor( edit.filepath, new vscode.Range( edit.range.start.line, diff --git a/extension/src/lang-server/codeLens.ts b/extension/src/lang-server/codeLens.ts index 2a362b62..e8766c3c 100644 --- a/extension/src/lang-server/codeLens.ts +++ b/extension/src/lang-server/codeLens.ts @@ -13,8 +13,8 @@ class SuggestionsCodeLensProvider implements vscode.CodeLensProvider { } let codeLenses: vscode.CodeLens[] = []; - for (let suggestion of suggestions) { - let range = new vscode.Range( + for (const suggestion of suggestions) { + const range = new vscode.Range( suggestion.oldRange.start, suggestion.newRange.end ); @@ -57,16 +57,16 @@ class PytestCodeLensProvider implements vscode.CodeLensProvider { document: vscode.TextDocument, token: vscode.CancellationToken ): vscode.CodeLens[] | Thenable { - let codeLenses: vscode.CodeLens[] = []; + const codeLenses: vscode.CodeLens[] = []; let lineno = 1; - let languageLibrary = getLanguageLibrary(document.fileName); + const languageLibrary = getLanguageLibrary(document.fileName); for (let line of document.getText().split("\n")) { if ( languageLibrary.lineIsFunctionDef(line) && languageLibrary.parseFunctionDefForName(line).startsWith("test_") ) { - let functionToTest = languageLibrary.parseFunctionDefForName(line); - let fileAndFunctionNameSpecifier = + const functionToTest = languageLibrary.parseFunctionDefForName(line); + const fileAndFunctionNameSpecifier = document.fileName + "::" + functionToTest; codeLenses.push( new vscode.CodeLens(new vscode.Range(lineno, 0, lineno, 1), { @@ -85,12 +85,13 @@ class PytestCodeLensProvider implements vscode.CodeLensProvider { const allCodeLensProviders: { [langauge: string]: vscode.CodeLensProvider[] } = { - python: [new SuggestionsCodeLensProvider(), new PytestCodeLensProvider()], + // python: [new SuggestionsCodeLensProvider(), new PytestCodeLensProvider()], + "*": [new SuggestionsCodeLensProvider()], }; export function registerAllCodeLensProviders(context: vscode.ExtensionContext) { - for (let language in allCodeLensProviders) { - for (let codeLensProvider of allCodeLensProviders[language]) { + for (const language in allCodeLensProviders) { + for (const codeLensProvider of allCodeLensProviders[language]) { context.subscriptions.push( vscode.languages.registerCodeLensProvider(language, codeLensProvider) ); diff --git a/extension/src/suggestions.ts b/extension/src/suggestions.ts index c66fad86..5ac6e095 100644 --- a/extension/src/suggestions.ts +++ b/extension/src/suggestions.ts @@ -14,7 +14,7 @@ export const editorToSuggestions: Map< string, // URI of file SuggestionRanges[] > = new Map(); -export let currentSuggestion: Map = new Map(); // Map from editor URI to index of current SuggestionRanges in editorToSuggestions +export const currentSuggestion: Map = new Map(); // Map from editor URI to index of current SuggestionRanges in editorToSuggestions // When tab is reopened, rerender the decorations: vscode.window.onDidChangeActiveTextEditor((editor) => { @@ -25,16 +25,16 @@ vscode.workspace.onDidOpenTextDocument((doc) => { rerenderDecorations(doc.uri.toString()); }); -let newDecorationType = vscode.window.createTextEditorDecorationType({ +const newDecorationType = vscode.window.createTextEditorDecorationType({ backgroundColor: "rgb(0, 255, 0, 0.1)", isWholeLine: true, }); -let oldDecorationType = vscode.window.createTextEditorDecorationType({ +const oldDecorationType = vscode.window.createTextEditorDecorationType({ backgroundColor: "rgb(255, 0, 0, 0.1)", isWholeLine: true, cursor: "pointer", }); -let newSelDecorationType = vscode.window.createTextEditorDecorationType({ +const newSelDecorationType = vscode.window.createTextEditorDecorationType({ backgroundColor: "rgb(0, 255, 0, 0.25)", isWholeLine: true, after: { @@ -42,7 +42,7 @@ let newSelDecorationType = vscode.window.createTextEditorDecorationType({ margin: "0 0 0 1em", }, }); -let oldSelDecorationType = vscode.window.createTextEditorDecorationType({ +const oldSelDecorationType = vscode.window.createTextEditorDecorationType({ backgroundColor: "rgb(255, 0, 0, 0.25)", isWholeLine: true, after: { @@ -52,19 +52,19 @@ let oldSelDecorationType = vscode.window.createTextEditorDecorationType({ }); export function rerenderDecorations(editorUri: string) { - let suggestions = editorToSuggestions.get(editorUri); - let idx = currentSuggestion.get(editorUri); - let editor = vscode.window.visibleTextEditors.find( + const suggestions = editorToSuggestions.get(editorUri); + const idx = currentSuggestion.get(editorUri); + const editor = vscode.window.visibleTextEditors.find( (editor) => editor.document.uri.toString() === editorUri ); if (!suggestions || !editor) return; - let olds: vscode.Range[] = [], - news: vscode.Range[] = [], - oldSels: vscode.Range[] = [], - newSels: vscode.Range[] = []; + const olds: vscode.Range[] = []; + const news: vscode.Range[] = []; + const oldSels: vscode.Range[] = []; + const newSels: vscode.Range[] = []; for (let i = 0; i < suggestions.length; i++) { - let suggestion = suggestions[i]; + const suggestion = suggestions[i]; if (typeof idx != "undefined" && idx === i) { if (suggestion.newSelected) { olds.push(suggestion.oldRange); @@ -92,14 +92,14 @@ export function rerenderDecorations(editorUri: string) { } export function suggestionDownCommand() { - let editor = vscode.window.activeTextEditor; + const editor = vscode.window.activeTextEditor; if (!editor) return; - let editorUri = editor.document.uri.toString(); - let suggestions = editorToSuggestions.get(editorUri); - let idx = currentSuggestion.get(editorUri); + const editorUri = editor.document.uri.toString(); + const suggestions = editorToSuggestions.get(editorUri); + const idx = currentSuggestion.get(editorUri); if (!suggestions || idx === undefined) return; - let suggestion = suggestions[idx]; + const suggestion = suggestions[idx]; if (!suggestion.newSelected) { suggestion.newSelected = true; } else if (idx + 1 < suggestions.length) { @@ -109,14 +109,14 @@ export function suggestionDownCommand() { } export function suggestionUpCommand() { - let editor = vscode.window.activeTextEditor; + const editor = vscode.window.activeTextEditor; if (!editor) return; - let editorUri = editor.document.uri.toString(); - let suggestions = editorToSuggestions.get(editorUri); - let idx = currentSuggestion.get(editorUri); + const editorUri = editor.document.uri.toString(); + const suggestions = editorToSuggestions.get(editorUri); + const idx = currentSuggestion.get(editorUri); if (!suggestions || idx === undefined) return; - let suggestion = suggestions[idx]; + const suggestion = suggestions[idx]; if (suggestion.newSelected) { suggestion.newSelected = false; } else if (idx > 0) { @@ -130,10 +130,10 @@ function selectSuggestion( accept: SuggestionSelectionOption, key: SuggestionRanges | null = null ) { - let editor = vscode.window.activeTextEditor; + const editor = vscode.window.activeTextEditor; if (!editor) return; - let editorUri = editor.document.uri.toString(); - let suggestions = editorToSuggestions.get(editorUri); + const editorUri = editor.document.uri.toString(); + const suggestions = editorToSuggestions.get(editorUri); if (!suggestions) return; @@ -218,14 +218,14 @@ export async function showSuggestion( range: vscode.Range, suggestion: string ): Promise { - let existingCode = await readFileAtRange( + 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 - let slines = suggestion.split("\n"); - let elines = existingCode.split("\n"); + 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]) { @@ -255,7 +255,7 @@ export async function showSuggestion( ) ); - let editor = await openEditorAndRevealRange(editorFilename, range); + const editor = await openEditorAndRevealRange(editorFilename, range); if (!editor) return Promise.resolve(false); return new Promise((resolve, reject) => { diff --git a/extension/src/util/vscode.ts b/extension/src/util/vscode.ts index a76b53c7..3110d589 100644 --- a/extension/src/util/vscode.ts +++ b/extension/src/util/vscode.ts @@ -118,9 +118,11 @@ export async function readFileAtRange( ) ); } else { - let firstLine = lines[range.start.line].slice(range.start.character); - let lastLine = lines[range.end.line].slice(0, range.end.character); - let middleLines = lines.slice(range.start.line + 1, range.end.line); + const firstLine = lines[range.start.line].slice( + range.start.character + ); + const lastLine = lines[range.end.line].slice(0, range.end.character); + const middleLines = lines.slice(range.start.line + 1, range.end.line); resolve([firstLine, ...middleLines, lastLine].join("\n")); } } @@ -144,7 +146,7 @@ export function openEditorAndRevealRange( setInterval(() => { resolve(null); }, 200); - }) + }); } showTextDocumentInProcess = true; vscode.window @@ -158,10 +160,10 @@ export function openEditorAndRevealRange( } resolve(editor); showTextDocumentInProcess = false; - }) - } catch (err) { - console.log(err); - } - }); + }); + } catch (err) { + console.log(err); + } + }); }); } -- 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 'extension') 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 'extension') 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 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 'extension') 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 5dfd7b8ee8d79c47bf39ea8a97872f1e2af23c35 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 27 Jun 2023 09:51:37 -0700 Subject: accept/reject all --- extension/package.json | 20 ++++++++++++++++++++ extension/src/commands.ts | 4 ++++ extension/src/suggestions.ts | 32 +++++++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 3 deletions(-) (limited to 'extension') diff --git a/extension/package.json b/extension/package.json index a9b8660b..63a49173 100644 --- a/extension/package.json +++ b/extension/package.json @@ -85,6 +85,16 @@ "command": "continue.rejectSuggestion", "category": "Continue", "title": "Reject Suggestion" + }, + { + "command": "continue.acceptAllSuggestions", + "category": "Continue", + "title": "Accept All Suggestions" + }, + { + "command": "continue.rejectAllSuggestions", + "category": "Continue", + "title": "Reject All Suggestions" } ], "keybindings": [ @@ -107,6 +117,16 @@ "command": "continue.acceptSuggestion", "mac": "shift+ctrl+enter", "key": "shift+ctrl+enter" + }, + { + "command": "continue.acceptAllSuggestions", + "mac": "shift+cmd+enter", + "key": "shift+ctrl+enter" + }, + { + "command": "continue.rejectAllSuggestions", + "mac": "shift+cmd+backspace", + "key": "shift+ctrl+backspace" } ], "menus": { diff --git a/extension/src/commands.ts b/extension/src/commands.ts index 22e15c43..424c238a 100644 --- a/extension/src/commands.ts +++ b/extension/src/commands.ts @@ -10,6 +10,8 @@ import { rejectSuggestionCommand, suggestionDownCommand, suggestionUpCommand, + acceptAllSuggestionsCommand, + rejectAllSuggestionsCommand, } from "./suggestions"; import * as bridge from "./bridge"; import { debugPanelWebview, setupDebugPanel } from "./debugPanel"; @@ -61,6 +63,8 @@ const commandsMap: { [command: string]: (...args: any) => any } = { "continue.suggestionUp": suggestionUpCommand, "continue.acceptSuggestion": acceptSuggestionCommand, "continue.rejectSuggestion": rejectSuggestionCommand, + "continue.acceptAllSuggestions": acceptAllSuggestionsCommand, + "continue.rejectAllSuggestions": rejectAllSuggestionsCommand, "continue.focusContinueInput": async () => { vscode.commands.executeCommand("continue.continueGUIView.focus"); debugPanelWebview?.postMessage({ diff --git a/extension/src/suggestions.ts b/extension/src/suggestions.ts index 9b358899..4631c33e 100644 --- a/extension/src/suggestions.ts +++ b/extension/src/suggestions.ts @@ -238,6 +238,26 @@ export function acceptSuggestionCommand(key: SuggestionRanges | null = null) { selectSuggestion("selected", key); } +function handleAllSuggestions(accept: boolean) { + const editor = vscode.window.activeTextEditor; + if (!editor) return; + const editorUri = editor.document.uri.toString(); + const suggestions = editorToSuggestions.get(editorUri); + if (!suggestions) return; + + while (suggestions.length > 0) { + selectSuggestion(accept ? "new" : "old"); + } +} + +export function acceptAllSuggestionsCommand() { + handleAllSuggestions(true); +} + +export function rejectAllSuggestionsCommand() { + handleAllSuggestions(false); +} + export async function rejectSuggestionCommand( key: SuggestionRanges | null = null ) { @@ -292,9 +312,15 @@ export async function showSuggestion( return new Promise((resolve, reject) => { editor! - .edit((edit) => { - edit.insert(new vscode.Position(range.end.line, 0), suggestion + "\n"); - }) + .edit( + (edit) => { + edit.insert( + new vscode.Position(range.end.line, 0), + suggestion + "\n" + ); + }, + { undoStopBefore: false, undoStopAfter: false } + ) .then( (success) => { if (success) { -- 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 'extension') 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 'extension') 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