mirror of
https://github.com/Iheuzio/gpt-contextfiles.git
synced 2025-07-18 14:00:48 +00:00
fix(organize-files): easier to debug under src
This commit is contained in:
parent
5350ea703c
commit
6994b23aa2
@ -2,7 +2,7 @@
|
||||
"name": "gpt-contextfiles",
|
||||
"displayName": "GPT-ContextFiles",
|
||||
"description": "Choose the files to pass into GPT to provide a question with multiple files",
|
||||
"version": "0.2.1",
|
||||
"version": "0.2.2",
|
||||
"engines": {
|
||||
"vscode": "^1.79.0"
|
||||
},
|
||||
@ -39,7 +39,7 @@
|
||||
"onCommand:extension.openGPTContextPanel",
|
||||
"onCommand:extension.gpt-context-sidebar"
|
||||
],
|
||||
"main": "./extension.js",
|
||||
"main": "./src/extension.js",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
|
84
src/commands.js
Normal file
84
src/commands.js
Normal file
@ -0,0 +1,84 @@
|
||||
const vscode = require('vscode');
|
||||
const { selectedFiles, fileDataProvider, handleQuestionSubmission } = require('./gptContext');
|
||||
const FileItem = require('./fileItem');
|
||||
const { getWebviewContent } = require('./webviewPanel');
|
||||
|
||||
const addFilesCommand = vscode.commands.registerCommand('extension.addFilesToGPTContext', () => {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor) {
|
||||
const uri = editor.document.uri;
|
||||
const existingFileIndex = selectedFiles.findIndex(file => file.uri.fsPath === uri.fsPath);
|
||||
|
||||
if (existingFileIndex !== -1) {
|
||||
// File already exists, remove it from the list
|
||||
selectedFiles.splice(existingFileIndex, 1);
|
||||
} else {
|
||||
// Add the file to the list with selected state
|
||||
selectedFiles.push(new FileItem(uri, true));
|
||||
}
|
||||
|
||||
fileDataProvider.refresh();
|
||||
}
|
||||
});
|
||||
|
||||
const openGPTContextPanelCommand = vscode.commands.registerCommand('extension.openGPTContextPanel', () => {
|
||||
const panel = vscode.window.createWebviewPanel(
|
||||
'gptContextPanel',
|
||||
'GPT Context',
|
||||
vscode.ViewColumn.One,
|
||||
{
|
||||
enableScripts: true
|
||||
}
|
||||
);
|
||||
|
||||
panel.webview.html = getWebviewContent();
|
||||
|
||||
panel.webview.onDidReceiveMessage(async message => {
|
||||
if (message.command === 'submitQuestion') {
|
||||
await handleQuestionSubmission(panel, message.text, message.selectedUris);
|
||||
} else if (message.command === 'toggleFileSelection') {
|
||||
const uri = message.uri;
|
||||
const file = selectedFiles.find(file => file.uri.fsPath === uri);
|
||||
if (file) {
|
||||
file.toggleSelected();
|
||||
fileDataProvider.refresh();
|
||||
}
|
||||
} else if (message.command === 'clearSelectedFiles') {
|
||||
const clearedFiles = selectedFiles.filter(file => file.selected === false);
|
||||
selectedFiles.length = 0; // Clear the array
|
||||
clearedFiles.forEach(file => {
|
||||
fileDataProvider.refresh();
|
||||
});
|
||||
panel.webview.html = getWebviewContent();
|
||||
} else if (message.command === 'refreshFiles') {
|
||||
fileDataProvider.refresh();
|
||||
panel.webview.html = getWebviewContent();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const refreshSelectedFilesCommand = vscode.commands.registerCommand('extension.refreshSelectedFiles', () => {
|
||||
fileDataProvider.refresh();
|
||||
});
|
||||
|
||||
// Command for clearing the selected files
|
||||
const clearSelectedFilesCommand = vscode.commands.registerCommand('extension.clearSelectedFiles', () => {
|
||||
selectedFiles.forEach(file => {
|
||||
file.selected = false;
|
||||
});
|
||||
fileDataProvider.refresh();
|
||||
});
|
||||
|
||||
// Command for refreshing all files
|
||||
const refreshFilesCommand = vscode.commands.registerCommand('extension.refreshFiles', () => {
|
||||
fileDataProvider.refresh();
|
||||
});
|
||||
|
||||
|
||||
module.exports = {
|
||||
addFilesCommand,
|
||||
openGPTContextPanelCommand,
|
||||
refreshSelectedFilesCommand,
|
||||
clearSelectedFilesCommand,
|
||||
refreshFilesCommand
|
||||
};
|
52
src/extension.js
Normal file
52
src/extension.js
Normal file
@ -0,0 +1,52 @@
|
||||
const vscode = require('vscode');
|
||||
const { addFilesCommand, openGPTContextPanelCommand, refreshSelectedFilesCommand, clearSelectedFilesCommand, refreshFilesCommand } = require('./commands');
|
||||
const { getWebviewContent } = require('./webviewPanel');
|
||||
const { selectedFiles, fileDataProvider, handleQuestionSubmission } = require('./gptContext');
|
||||
|
||||
function activate(context) {
|
||||
context.subscriptions.push(addFilesCommand);
|
||||
context.subscriptions.push(openGPTContextPanelCommand);
|
||||
context.subscriptions.push(refreshSelectedFilesCommand);
|
||||
context.subscriptions.push(clearSelectedFilesCommand);
|
||||
context.subscriptions.push(refreshFilesCommand);
|
||||
vscode.window.registerTreeDataProvider('selectedFiles', fileDataProvider);
|
||||
|
||||
const provider = {
|
||||
resolveWebviewView(webviewView) {
|
||||
webviewView.webview.options = {
|
||||
enableScripts: true
|
||||
};
|
||||
webviewView.webview.html = getWebviewContent();
|
||||
webviewView.webview.onDidReceiveMessage(async message => {
|
||||
if (message.command === 'toggleFileSelection') {
|
||||
const uri = message.uri;
|
||||
const file = selectedFiles.find(file => file.uri.fsPath === uri);
|
||||
if (file) {
|
||||
file.toggleSelected();
|
||||
fileDataProvider.refresh();
|
||||
}
|
||||
} else if (message.command === 'clearSelectedFiles') {
|
||||
const clearedFiles = selectedFiles.filter(file => file.selected === false);
|
||||
selectedFiles.length = 0; // Clear the array
|
||||
clearedFiles.forEach(file => {
|
||||
fileDataProvider.refresh();
|
||||
});
|
||||
webviewView.webview.html = getWebviewContent();
|
||||
} else if (message.command === 'refreshFiles') {
|
||||
fileDataProvider.refresh();
|
||||
webviewView.webview.html = getWebviewContent();
|
||||
} else if (message.command === 'submitQuestion') {
|
||||
await handleQuestionSubmission(webviewView, message.text, message.selectedUris);
|
||||
} else if (message.command === 'codeCopied') {
|
||||
vscode.window.showInformationMessage('Code copied to clipboard');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
context.subscriptions.push(vscode.window.registerWebviewViewProvider('gpt-context-sidebar', provider));
|
||||
|
||||
}
|
||||
|
||||
|
||||
exports.activate = activate;
|
38
src/fileDataProvider.js
Normal file
38
src/fileDataProvider.js
Normal file
@ -0,0 +1,38 @@
|
||||
const vscode = require('vscode');
|
||||
const FileItem = require('./fileItem.js');
|
||||
|
||||
// Represents the selected files in the file explorer
|
||||
const selectedFiles = [];
|
||||
|
||||
// Tree data provider for the selected files
|
||||
class FileDataProvider {
|
||||
constructor() {
|
||||
this._onDidChangeTreeData = new vscode.EventEmitter();
|
||||
this.onDidChangeTreeData = this._onDidChangeTreeData.event;
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
|
||||
getTreeItem(element) {
|
||||
return {
|
||||
label: element.uri.fsPath,
|
||||
collapsibleState: vscode.TreeItemCollapsibleState.None
|
||||
};
|
||||
}
|
||||
|
||||
getChildren(element) {
|
||||
if (element) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Return only the selected files
|
||||
return selectedFiles.filter(file => file.selected);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
FileDataProvider,
|
||||
selectedFiles
|
||||
};
|
12
src/fileItem.js
Normal file
12
src/fileItem.js
Normal file
@ -0,0 +1,12 @@
|
||||
class FileItem {
|
||||
constructor(uri, selected = false) {
|
||||
this.uri = uri;
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
toggleSelected() {
|
||||
this.selected = !this.selected;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FileItem;
|
64
src/gptContext.js
Normal file
64
src/gptContext.js
Normal file
@ -0,0 +1,64 @@
|
||||
const vscode = require('vscode');
|
||||
const { Configuration, OpenAIApi } = require("openai");
|
||||
const FileDataProvider = require('./fileDataProvider');
|
||||
const FileItem = require('./fileItem');
|
||||
const { getWebviewContent } = require('./webviewPanel');
|
||||
|
||||
|
||||
const configuration = new Configuration({
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
});
|
||||
|
||||
const openai = new OpenAIApi(configuration);
|
||||
|
||||
const selectedFiles = FileDataProvider.selectedFiles;
|
||||
const fileDataProvider = new FileDataProvider.FileDataProvider();
|
||||
|
||||
async function handleQuestionSubmission(panel, question, selectedUris) {
|
||||
// Update the selectedFiles array based on the selectedUris
|
||||
selectedFiles.forEach(file => {
|
||||
file.selected = selectedUris.includes(file.uri.fsPath);
|
||||
});
|
||||
|
||||
fileDataProvider.refresh();
|
||||
|
||||
const fileContents = selectedFiles
|
||||
.filter(file => file.selected)
|
||||
.map(file => {
|
||||
const document = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === file.uri.fsPath);
|
||||
if (document) {
|
||||
const lines = document.getText().split('\n');
|
||||
const formattedLines = lines.map(line => `\t${line}`).join('\n');
|
||||
return `${file.uri.fsPath}:\n\`\`\`\n${formattedLines}\n\`\`\``;
|
||||
}
|
||||
return '';
|
||||
})
|
||||
.join('\n\n');
|
||||
|
||||
// Call OpenAI API with the question and file contents
|
||||
try {
|
||||
const chatCompletion = await openai.createChatCompletion({
|
||||
model: "gpt-3.5-turbo-16k",
|
||||
messages: [
|
||||
{ role: "system", content: "Answer the coding questions, only provide the code and documentation, explaining the solution after providing the code." },
|
||||
{ role: "user", content: question + "\n" + fileContents},
|
||||
],
|
||||
});
|
||||
|
||||
// Extract the answer from the OpenAI response
|
||||
const answer = chatCompletion.data.choices[0].message.content;
|
||||
|
||||
// Update the webview content to display only the OpenAI response
|
||||
panel.webview.html = getWebviewContent(answer, question);
|
||||
} catch (error) {
|
||||
// Handle any errors from the OpenAI API
|
||||
console.error("Failed to get OpenAI response:", error);
|
||||
panel.webview.html = getWebviewContent(`Failed to get response from OpenAI API. Error: ${error.message}`, question);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
handleQuestionSubmission,
|
||||
fileDataProvider,
|
||||
selectedFiles
|
||||
};
|
@ -1,179 +1,6 @@
|
||||
const vscode = require('vscode');
|
||||
const { Configuration, OpenAIApi } = require("openai");
|
||||
const { selectedFiles } = require('./fileDataProvider');
|
||||
|
||||
// move these into the script so that instead of echoing the question and the contents,
|
||||
// it will echo the question, followed by the answer from the response when the submit button is pressed.
|
||||
const configuration = new Configuration({
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
});
|
||||
|
||||
const openai = new OpenAIApi(configuration);
|
||||
|
||||
// Represents a file item in the file explorer
|
||||
class FileItem {
|
||||
constructor(uri, selected = false) {
|
||||
this.uri = uri;
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
toggleSelected() {
|
||||
this.selected = !this.selected;
|
||||
}
|
||||
}
|
||||
|
||||
// Represents the selected files in the file explorer
|
||||
const selectedFiles = [];
|
||||
|
||||
// Tree data provider for the selected files
|
||||
class FileDataProvider {
|
||||
constructor() {
|
||||
this._onDidChangeTreeData = new vscode.EventEmitter();
|
||||
this.onDidChangeTreeData = this._onDidChangeTreeData.event;
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
|
||||
getTreeItem(element) {
|
||||
return {
|
||||
label: element.uri.fsPath,
|
||||
collapsibleState: vscode.TreeItemCollapsibleState.None
|
||||
};
|
||||
}
|
||||
|
||||
getChildren(element) {
|
||||
if (element) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Return only the selected files
|
||||
return selectedFiles.filter(file => file.selected);
|
||||
}
|
||||
}
|
||||
|
||||
// Command for adding files to gpt-contextfiles
|
||||
const addFilesCommand = vscode.commands.registerCommand('extension.addFilesToGPTContext', () => {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor) {
|
||||
const uri = editor.document.uri;
|
||||
const existingFileIndex = selectedFiles.findIndex(file => file.uri.fsPath === uri.fsPath);
|
||||
|
||||
if (existingFileIndex !== -1) {
|
||||
// File already exists, remove it from the list
|
||||
selectedFiles.splice(existingFileIndex, 1);
|
||||
} else {
|
||||
// Add the file to the list with selected state
|
||||
selectedFiles.push(new FileItem(uri, true));
|
||||
}
|
||||
|
||||
fileDataProvider.refresh();
|
||||
}
|
||||
});
|
||||
|
||||
const fileDataProvider = new FileDataProvider();
|
||||
|
||||
// Function to handle question submission
|
||||
async function handleQuestionSubmission(panel, question, selectedUris) {
|
||||
// Update the selectedFiles array based on the selectedUris
|
||||
selectedFiles.forEach(file => {
|
||||
file.selected = selectedUris.includes(file.uri.fsPath);
|
||||
});
|
||||
|
||||
fileDataProvider.refresh();
|
||||
|
||||
const fileContents = selectedFiles
|
||||
.filter(file => file.selected)
|
||||
.map(file => {
|
||||
const document = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === file.uri.fsPath);
|
||||
if (document) {
|
||||
const lines = document.getText().split('\n');
|
||||
const formattedLines = lines.map(line => `\t${line}`).join('\n');
|
||||
return `${file.uri.fsPath}:\n\`\`\`\n${formattedLines}\n\`\`\``;
|
||||
}
|
||||
return '';
|
||||
})
|
||||
.join('\n\n');
|
||||
|
||||
// Call OpenAI API with the question and file contents
|
||||
try {
|
||||
const chatCompletion = await openai.createChatCompletion({
|
||||
model: "gpt-3.5-turbo-16k",
|
||||
messages: [
|
||||
{ role: "system", content: "Answer the coding questions, only provide the code and documentation, explaining the solution after providing the code." },
|
||||
{ role: "user", content: question + "\n" + fileContents},
|
||||
],
|
||||
});
|
||||
|
||||
// Extract the answer from the OpenAI response
|
||||
const answer = chatCompletion.data.choices[0].message.content;
|
||||
|
||||
// Update the webview content to display only the OpenAI response
|
||||
panel.webview.html = getWebviewContent(answer, question);
|
||||
} catch (error) {
|
||||
// Handle any errors from the OpenAI API
|
||||
console.error("Failed to get OpenAI response:", error);
|
||||
panel.webview.html = getWebviewContent(`Failed to get response from OpenAI API. Error: ${error.message}`, question);
|
||||
}
|
||||
}
|
||||
|
||||
// Command for displaying the webview panel
|
||||
const openGPTContextPanelCommand = vscode.commands.registerCommand('extension.openGPTContextPanel', () => {
|
||||
const panel = vscode.window.createWebviewPanel(
|
||||
'gptContextPanel',
|
||||
'GPT Context',
|
||||
vscode.ViewColumn.One,
|
||||
{
|
||||
enableScripts: true
|
||||
}
|
||||
);
|
||||
|
||||
panel.webview.html = getWebviewContent();
|
||||
|
||||
panel.webview.onDidReceiveMessage(async message => {
|
||||
if (message.command === 'submitQuestion') {
|
||||
await handleQuestionSubmission(panel, message.text, message.selectedUris);
|
||||
} else if (message.command === 'toggleFileSelection') {
|
||||
const uri = message.uri;
|
||||
const file = selectedFiles.find(file => file.uri.fsPath === uri);
|
||||
if (file) {
|
||||
file.toggleSelected();
|
||||
fileDataProvider.refresh();
|
||||
}
|
||||
} else if (message.command === 'clearSelectedFiles') {
|
||||
const clearedFiles = selectedFiles.filter(file => file.selected === false);
|
||||
selectedFiles.length = 0; // Clear the array
|
||||
clearedFiles.forEach(file => {
|
||||
fileDataProvider.refresh();
|
||||
});
|
||||
panel.webview.html = getWebviewContent();
|
||||
} else if (message.command === 'refreshFiles') {
|
||||
fileDataProvider.refresh();
|
||||
panel.webview.html = getWebviewContent();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Command for refreshing the selected files
|
||||
const refreshSelectedFilesCommand = vscode.commands.registerCommand('extension.refreshSelectedFiles', () => {
|
||||
fileDataProvider.refresh();
|
||||
});
|
||||
|
||||
// Command for clearing the selected files
|
||||
const clearSelectedFilesCommand = vscode.commands.registerCommand('extension.clearSelectedFiles', () => {
|
||||
selectedFiles.forEach(file => {
|
||||
file.selected = false;
|
||||
});
|
||||
fileDataProvider.refresh();
|
||||
});
|
||||
|
||||
// Command for refreshing all files
|
||||
const refreshFilesCommand = vscode.commands.registerCommand('extension.refreshFiles', () => {
|
||||
fileDataProvider.refresh();
|
||||
});
|
||||
|
||||
// Helper function to generate the HTML content for the webview panel
|
||||
function getWebviewContent(apiResponse = '', question = '') {
|
||||
const fileList = selectedFiles
|
||||
.map(
|
||||
@ -584,53 +411,6 @@ function getWebviewContent(apiResponse = '', question = '') {
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Activates the extension
|
||||
function activate(context) {
|
||||
context.subscriptions.push(addFilesCommand);
|
||||
context.subscriptions.push(openGPTContextPanelCommand);
|
||||
context.subscriptions.push(refreshSelectedFilesCommand);
|
||||
context.subscriptions.push(clearSelectedFilesCommand);
|
||||
context.subscriptions.push(refreshFilesCommand);
|
||||
vscode.window.registerTreeDataProvider('selectedFiles', fileDataProvider);
|
||||
|
||||
const provider = {
|
||||
resolveWebviewView(webviewView) {
|
||||
webviewView.webview.options = {
|
||||
enableScripts: true
|
||||
};
|
||||
webviewView.webview.html = getWebviewContent();
|
||||
webviewView.webview.onDidReceiveMessage(async message => {
|
||||
if (message.command === 'toggleFileSelection') {
|
||||
const uri = message.uri;
|
||||
const file = selectedFiles.find(file => file.uri.fsPath === uri);
|
||||
if (file) {
|
||||
file.toggleSelected();
|
||||
fileDataProvider.refresh();
|
||||
}
|
||||
} else if (message.command === 'clearSelectedFiles') {
|
||||
const clearedFiles = selectedFiles.filter(file => file.selected === false);
|
||||
selectedFiles.length = 0; // Clear the array
|
||||
clearedFiles.forEach(file => {
|
||||
fileDataProvider.refresh();
|
||||
});
|
||||
webviewView.webview.html = getWebviewContent();
|
||||
} else if (message.command === 'refreshFiles') {
|
||||
fileDataProvider.refresh();
|
||||
webviewView.webview.html = getWebviewContent();
|
||||
} else if (message.command === 'submitQuestion') {
|
||||
await handleQuestionSubmission(webviewView, message.text, message.selectedUris);
|
||||
} else if (message.command === 'codeCopied') {
|
||||
vscode.window.showInformationMessage('Code copied to clipboard');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
context.subscriptions.push(vscode.window.registerWebviewViewProvider('gpt-context-sidebar', provider));
|
||||
|
||||
}
|
||||
|
||||
|
||||
exports.activate = activate;
|
||||
module.exports = {
|
||||
getWebviewContent
|
||||
};
|
Loading…
Reference in New Issue
Block a user