new WORKING Version
This commit is contained in:
parent
f0c5bb0685
commit
e160fee3f9
14
package.json
14
package.json
|
@ -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,
|
||||
|
|
|
@ -38,10 +38,8 @@ 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);
|
||||
|
@ -50,53 +48,19 @@ function getContextLines(document: vscode.TextDocument, position: vscode.Positio
|
|||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue