new WORKING Version

This commit is contained in:
Falko Victor Habel 2024-08-21 12:46:48 +02:00
parent f0c5bb0685
commit e160fee3f9
2 changed files with 21 additions and 78 deletions

View File

@ -2,16 +2,13 @@
"name": "fabelous-autocoder",
"displayName": "Fabelous Autocoder",
"description": "A simple to use Ollama autocompletion engine with options exposed and streaming functionality",
"version": "0.1.69",
"version": "0.1.764",
"icon": "icon.png",
"publisher": "fabel",
"license": "CC BY-ND 4.0",
"bugs": {
"url": "https://gitea.fabelous.app/fabel/Fabelous-Autocoder/issues"
},
"sponsor": {
"url": "https://ko-fi.com/natehedge"
},
"repository": {
"type": "git",
"url": "https://gitea.fabelous.app/fabel/Fabelous-Autocoder"
@ -26,7 +23,6 @@
],
"keywords": [
"ollama",
"gpt",
"coding",
"autocomplete",
"open source",
@ -35,7 +31,7 @@
"llm"
],
"galleryBanner": {
"color": "#f5ead1"
"color": "#133773"
},
"activationEvents": [
"onStartupFinished"
@ -60,12 +56,6 @@
"default": "",
"description": "The model to use for generating completions"
},
"fabelous-autocoder.message header": {
"type": "string",
"editPresentation": "multilineText",
"default": "The following is a complete {LANG} file named {FILE_NAME} in the project {PROJECT_NAME}. Anything NOT code is written as a CODE COMMENT. \n\n```\n",
"description": "Pseudo-system prompt, optimized for code completion. It is recommended to keep the format the same if modified. Leave blank for no formatting (raw)."
},
"fabelous-autocoder.max tokens predicted": {
"type": "integer",
"default": 1000,

View File

@ -38,65 +38,29 @@ vscode.workspace.onDidChangeConfiguration(updateVSConfig);
function getContextLines(document: vscode.TextDocument, position: vscode.Position): string {
const lines = [];
const lineCount = document.lineCount;
const startLine = Math.max(0, position.line - promptWindowSize / 2);
const endLine = Math.min(lineCount - 1, position.line + promptWindowSize / 2);
const startLine = Math.max(0, position.line - 1);
const endLine = position.line;
for (let i = startLine; i <= endLine; i++) {
lines.push(document.lineAt(i).text);
}
return lines.join("\n");
}
function createFIMPrompt(prefix: string, suffix: string, language: string): string {
return `<fim_prefix>${prefix}<fim_middle><fim_suffix>${suffix}\n\`\`\`${language}\n`;
function createFIMPrompt(prefix: string, language: string): string {
return `<fim_prefix>${prefix}<fim_middle><fim_suffix>${language}\n`;
}
function removeMatchingPrefix(generatedContent: string): string {
const functionHeaderPatterns = [
// Java, C#, TypeScript, JavaScript
/^(public|private|protected)?\s*(static\s+)?(async\s+)?\w+(\s*<[^>]+>)?\s+\w+\s*\([^)]*\)\s*{/m,
// Python
/^def\s+\w+\s*\([^)]*\):/m,
// C++, C
/^(\w+\s+)*\w+\s+\w+\s*\([^)]*\)\s*{/m,
// Go
/^func\s+\w+\s*\([^)]*\)(\s+\w+)?\s*{/m,
// Rust
/^(pub\s+)?(fn|async fn)\s+\w+\s*(<[^>]+>)?\s*\([^)]*\)(\s*->\s*\w+)?\s*{/m
];
const lines = generatedContent.split('\n');
const firstNonEmptyLineIndex = lines.findIndex(line => line.trim() !== '');
if (firstNonEmptyLineIndex === -1) {
return '\n' + generatedContent;
}
const firstLine = lines[firstNonEmptyLineIndex];
for (const pattern of functionHeaderPatterns) {
if (pattern.test(firstLine)) {
lines.splice(firstNonEmptyLineIndex, 1);
return '\n' + lines.join('\n');
}
}
return '\n' + generatedContent;
}
async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationToken?: vscode.CancellationToken) {
const document = textEditor.document;
const position = textEditor.selection.active;
const context = getContextLines(document, position);
const lines = context.split("\n");
const currentLineIndex = position.line - Math.max(0, position.line - promptWindowSize / 2);
const prefix = lines.slice(0, currentLineIndex + 1).join("\n");
const suffix = lines.slice(currentLineIndex + 1).join("\n");
const fimPrompt = createFIMPrompt(prefix, suffix, document.languageId);
const fimPrompt = createFIMPrompt(context, document.languageId);
vscode.window.withProgress(
{
@ -141,16 +105,21 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo
// Remove any FIM tags and leading/trailing whitespace
completionText = completionText.replace(/<fim_middle>|<fim_suffix>|<fim_prefix>/g, '').trim();
completionText = removeMatchingPrefix(completionText);
// Remove the context lines
const startLine = Math.max(0, position.line - 1);
const endLine = position.line;
const rangeToReplace = new vscode.Range(
new vscode.Position(startLine, 0),
new vscode.Position(endLine, document.lineAt(endLine).text.length)
);
// Apply the edit
const edit = new vscode.WorkspaceEdit();
edit.insert(document.uri, position, completionText);
edit.replace(document.uri, rangeToReplace, completionText);
await vscode.workspace.applyEdit(edit);
// Move the cursor to the end of the inserted text
const newPosition = position.translate(0, completionText.length);
const newPosition = new vscode.Position(startLine + completionText.split('\n').length - 1, completionText.split('\n').pop()!.length);
textEditor.selection = new vscode.Selection(newPosition, newPosition);
progress.report({ message: "Fabelous completion finished." });
@ -165,6 +134,7 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo
);
}
async function provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, cancellationToken: vscode.CancellationToken) {
const item = new vscode.CompletionItem("Fabelous autocompletion");
item.insertText = new vscode.SnippetString('${1:}');
@ -176,11 +146,7 @@ async function provideCompletionItems(document: vscode.TextDocument, position: v
}
const context = getContextLines(document, position);
const lines = context.split("\n");
const currentLineIndex = position.line - Math.max(0, position.line - promptWindowSize / 2);
const prefix = lines.slice(0, currentLineIndex + 1).join("\n");
const suffix = lines.slice(currentLineIndex + 1).join("\n");
const fimPrompt = createFIMPrompt(prefix, suffix, document.languageId);
const fimPrompt = createFIMPrompt(context, document.languageId);
try {
const response_preview = await axios.post(apiEndpoint, {
@ -200,19 +166,6 @@ async function provideCompletionItems(document: vscode.TextDocument, position: v
cancellationToken.onCancellationRequested(() => c("Autocompletion request terminated by completion cancel"));
})
});
if (response_preview.data.response.trim() !== "") {
let previewText = response_preview.data.response.replace(/<fim_middle>|<fim_suffix>|<fim_prefix>/g, '').trimStart();
// Remove matching prefix and repeated function header
const existingContent = document.getText();
previewText = removeMatchingPrefix(existingContent);
if (previewText.trim() !== "") {
item.label = previewText;
item.insertText = previewText;
}
}
} catch (error) {
console.error("Error fetching preview:", error);
}