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",
|
"name": "fabelous-autocoder",
|
||||||
"displayName": "Fabelous Autocoder",
|
"displayName": "Fabelous Autocoder",
|
||||||
"description": "A simple to use Ollama autocompletion engine with options exposed and streaming functionality",
|
"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",
|
"icon": "icon.png",
|
||||||
"publisher": "fabel",
|
"publisher": "fabel",
|
||||||
"license": "CC BY-ND 4.0",
|
"license": "CC BY-ND 4.0",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://gitea.fabelous.app/fabel/Fabelous-Autocoder/issues"
|
"url": "https://gitea.fabelous.app/fabel/Fabelous-Autocoder/issues"
|
||||||
},
|
},
|
||||||
"sponsor": {
|
|
||||||
"url": "https://ko-fi.com/natehedge"
|
|
||||||
},
|
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://gitea.fabelous.app/fabel/Fabelous-Autocoder"
|
"url": "https://gitea.fabelous.app/fabel/Fabelous-Autocoder"
|
||||||
|
@ -26,7 +23,6 @@
|
||||||
],
|
],
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"ollama",
|
"ollama",
|
||||||
"gpt",
|
|
||||||
"coding",
|
"coding",
|
||||||
"autocomplete",
|
"autocomplete",
|
||||||
"open source",
|
"open source",
|
||||||
|
@ -35,7 +31,7 @@
|
||||||
"llm"
|
"llm"
|
||||||
],
|
],
|
||||||
"galleryBanner": {
|
"galleryBanner": {
|
||||||
"color": "#f5ead1"
|
"color": "#133773"
|
||||||
},
|
},
|
||||||
"activationEvents": [
|
"activationEvents": [
|
||||||
"onStartupFinished"
|
"onStartupFinished"
|
||||||
|
@ -60,12 +56,6 @@
|
||||||
"default": "",
|
"default": "",
|
||||||
"description": "The model to use for generating completions"
|
"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": {
|
"fabelous-autocoder.max tokens predicted": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"default": 1000,
|
"default": 1000,
|
||||||
|
|
|
@ -38,65 +38,29 @@ vscode.workspace.onDidChangeConfiguration(updateVSConfig);
|
||||||
|
|
||||||
function getContextLines(document: vscode.TextDocument, position: vscode.Position): string {
|
function getContextLines(document: vscode.TextDocument, position: vscode.Position): string {
|
||||||
const lines = [];
|
const lines = [];
|
||||||
const lineCount = document.lineCount;
|
const startLine = Math.max(0, position.line - 1);
|
||||||
|
const endLine = position.line;
|
||||||
const startLine = Math.max(0, position.line - promptWindowSize / 2);
|
|
||||||
const endLine = Math.min(lineCount - 1, position.line + promptWindowSize / 2);
|
|
||||||
|
|
||||||
for (let i = startLine; i <= endLine; i++) {
|
for (let i = startLine; i <= endLine; i++) {
|
||||||
lines.push(document.lineAt(i).text);
|
lines.push(document.lineAt(i).text);
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines.join("\n");
|
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) {
|
async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationToken?: vscode.CancellationToken) {
|
||||||
const document = textEditor.document;
|
const document = textEditor.document;
|
||||||
const position = textEditor.selection.active;
|
const position = textEditor.selection.active;
|
||||||
|
|
||||||
const context = getContextLines(document, position);
|
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(
|
vscode.window.withProgress(
|
||||||
{
|
{
|
||||||
|
@ -141,16 +105,21 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo
|
||||||
// Remove any FIM tags and leading/trailing whitespace
|
// Remove any FIM tags and leading/trailing whitespace
|
||||||
completionText = completionText.replace(/<fim_middle>|<fim_suffix>|<fim_prefix>/g, '').trim();
|
completionText = completionText.replace(/<fim_middle>|<fim_suffix>|<fim_prefix>/g, '').trim();
|
||||||
|
|
||||||
|
// Remove the context lines
|
||||||
completionText = removeMatchingPrefix(completionText);
|
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
|
// Apply the edit
|
||||||
const edit = new vscode.WorkspaceEdit();
|
const edit = new vscode.WorkspaceEdit();
|
||||||
edit.insert(document.uri, position, completionText);
|
edit.replace(document.uri, rangeToReplace, completionText);
|
||||||
await vscode.workspace.applyEdit(edit);
|
await vscode.workspace.applyEdit(edit);
|
||||||
|
|
||||||
// Move the cursor to the end of the inserted text
|
// 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);
|
textEditor.selection = new vscode.Selection(newPosition, newPosition);
|
||||||
|
|
||||||
progress.report({ message: "Fabelous completion finished." });
|
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) {
|
async function provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, cancellationToken: vscode.CancellationToken) {
|
||||||
const item = new vscode.CompletionItem("Fabelous autocompletion");
|
const item = new vscode.CompletionItem("Fabelous autocompletion");
|
||||||
item.insertText = new vscode.SnippetString('${1:}');
|
item.insertText = new vscode.SnippetString('${1:}');
|
||||||
|
@ -176,11 +146,7 @@ async function provideCompletionItems(document: vscode.TextDocument, position: v
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = getContextLines(document, position);
|
const context = getContextLines(document, position);
|
||||||
const lines = context.split("\n");
|
const fimPrompt = createFIMPrompt(context, document.languageId);
|
||||||
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);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response_preview = await axios.post(apiEndpoint, {
|
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"));
|
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) {
|
} catch (error) {
|
||||||
console.error("Error fetching preview:", error);
|
console.error("Error fetching preview:", error);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue