2023-05-05 21:27:40 +08:00
|
|
|
import * as vscode from 'vscode';
|
2023-08-21 11:52:00 +08:00
|
|
|
import * as fs from 'fs';
|
2023-05-05 21:27:40 +08:00
|
|
|
import { sendFileSelectMessage, sendCodeSelectMessage } from './util';
|
2023-05-16 14:24:24 +08:00
|
|
|
import ExtensionContextHolder from '../util/extensionContext';
|
2023-05-31 16:10:53 +08:00
|
|
|
import { TopicManager } from '../topic/topicManager';
|
2023-05-31 16:10:53 +08:00
|
|
|
import { TopicTreeDataProvider, TopicTreeItem } from '../panel/topicView';
|
|
|
|
import { FilePairManager } from '../util/diffFilePairs';
|
2023-05-31 16:10:53 +08:00
|
|
|
import { ApiKeyManager } from '../util/apiKey';
|
2023-07-06 07:42:44 +08:00
|
|
|
import { UiUtilWrapper } from '../util/uiUtil';
|
2023-07-06 07:42:44 +08:00
|
|
|
import { isValidApiKey } from '../handler/historyMessagesBase';
|
2023-05-31 16:10:53 +08:00
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
import { logger } from '../util/logger';
|
2023-08-21 11:52:00 +08:00
|
|
|
import { CommandRun, createTempSubdirectory, runCommandAndWriteOutput, runCommandStringAndWriteOutput, runCommandStringArrayAndWriteOutput } from '../util/commonUtil';
|
2023-08-21 11:52:00 +08:00
|
|
|
import { updateIndexingStatus, updateLastModifyTime } from '../util/askCodeUtil';
|
2023-08-21 11:52:00 +08:00
|
|
|
import { installAskCode as installAskCodeFun } from '../util/python_installer/install_askcode';
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
import { ProgressBar } from '../util/progressBar';
|
2023-08-21 11:52:00 +08:00
|
|
|
import path from 'path';
|
|
|
|
import { MessageHandler } from '../handler/messageHandler';
|
2023-08-24 10:45:51 +08:00
|
|
|
import { FT } from '../util/feature_flags/feature_toggles';
|
|
|
|
import { getPackageVersion } from '../util/python_installer/pip_package_version';
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-30 16:39:47 +08:00
|
|
|
import { exec } from 'child_process';
|
|
|
|
import { sendCommandListByDevChatRun } from '../handler/regCommandList';
|
2023-08-30 17:03:22 +08:00
|
|
|
import DevChat from "../toolwrapper/devchat";
|
2023-08-30 16:39:47 +08:00
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
let indexProcess: CommandRun | null = null;
|
2023-08-21 11:52:00 +08:00
|
|
|
let summaryIndexProcess: CommandRun | null = null;
|
2023-05-10 19:25:11 +08:00
|
|
|
|
2023-05-11 10:27:54 +08:00
|
|
|
function registerOpenChatPanelCommand(context: vscode.ExtensionContext) {
|
2023-05-31 16:10:53 +08:00
|
|
|
let disposable = vscode.commands.registerCommand('devchat.openChatPanel', async () => {
|
2023-05-16 17:49:13 +08:00
|
|
|
await vscode.commands.executeCommand('devchat-view.focus');
|
2023-05-31 16:10:53 +08:00
|
|
|
});
|
|
|
|
context.subscriptions.push(disposable);
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
|
2023-05-16 14:35:37 +08:00
|
|
|
async function ensureChatPanel(context: vscode.ExtensionContext): Promise<boolean> {
|
2023-05-31 16:10:53 +08:00
|
|
|
await vscode.commands.executeCommand('devchat-view.focus');
|
|
|
|
return true;
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function registerAddContextCommand(context: vscode.ExtensionContext) {
|
2023-06-13 11:05:42 +08:00
|
|
|
const callback = async (uri: { fsPath: any; }) => {
|
2023-05-31 16:10:53 +08:00
|
|
|
if (!await ensureChatPanel(context)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-13 11:05:42 +08:00
|
|
|
await sendFileSelectMessage(ExtensionContextHolder.provider?.view()!, uri.fsPath);
|
2023-05-31 16:10:53 +08:00
|
|
|
};
|
|
|
|
context.subscriptions.push(vscode.commands.registerCommand('devchat.addConext', callback));
|
|
|
|
context.subscriptions.push(vscode.commands.registerCommand('devchat.addConext_chinese', callback));
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function registerAskForCodeCommand(context: vscode.ExtensionContext) {
|
2023-05-31 16:10:53 +08:00
|
|
|
const callback = async () => {
|
|
|
|
const editor = vscode.window.activeTextEditor;
|
|
|
|
if (editor) {
|
|
|
|
if (!await ensureChatPanel(context)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const selectedText = editor.document.getText(editor.selection);
|
2023-07-24 08:16:47 +08:00
|
|
|
await sendCodeSelectMessage(ExtensionContextHolder.provider?.view()!, editor.document.fileName, selectedText, editor.selection.start.line);
|
2023-05-31 16:10:53 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
context.subscriptions.push(vscode.commands.registerCommand('devchat.askForCode', callback));
|
|
|
|
context.subscriptions.push(vscode.commands.registerCommand('devchat.askForCode_chinese', callback));
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function registerAskForFileCommand(context: vscode.ExtensionContext) {
|
2023-05-31 16:10:53 +08:00
|
|
|
const callback = async () => {
|
|
|
|
const editor = vscode.window.activeTextEditor;
|
|
|
|
if (editor) {
|
|
|
|
if (!await ensureChatPanel(context)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
await sendFileSelectMessage(ExtensionContextHolder.provider?.view()!, editor.document.fileName);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
context.subscriptions.push(vscode.commands.registerCommand('devchat.askForFile', callback));
|
|
|
|
context.subscriptions.push(vscode.commands.registerCommand('devchat.askForFile_chinese', callback));
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
|
2023-09-13 10:08:16 +08:00
|
|
|
function regAccessKeyCommand(context: vscode.ExtensionContext, provider: string) {
|
2023-05-31 16:10:53 +08:00
|
|
|
context.subscriptions.push(
|
2023-09-13 10:08:16 +08:00
|
|
|
vscode.commands.registerCommand(`DevChat.AccessKey.${provider}`, async () => {
|
2023-05-31 16:10:53 +08:00
|
|
|
const passwordInput: string = await vscode.window.showInputBox({
|
|
|
|
password: true,
|
2023-09-13 10:08:16 +08:00
|
|
|
title: `Input ${provider} Access Key`,
|
|
|
|
placeHolder: `Set ${provider} Access Key.(Leave blank if clearing stored key.)`
|
2023-08-03 15:09:34 +08:00
|
|
|
}) ?? '';
|
|
|
|
|
|
|
|
if (passwordInput.trim() !== "" && !isValidApiKey(passwordInput)) {
|
|
|
|
UiUtilWrapper.showErrorMessage("Your api key is invalid!");
|
|
|
|
return ;
|
|
|
|
}
|
2023-09-13 10:08:16 +08:00
|
|
|
await ApiKeyManager.writeApiKeySecret(passwordInput, provider);
|
2023-08-03 15:09:34 +08:00
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-09-13 10:08:16 +08:00
|
|
|
export function registerAccessKeySettingCommand(context: vscode.ExtensionContext) {
|
|
|
|
regAccessKeyCommand(context, "OpenAI");
|
|
|
|
regAccessKeyCommand(context, "Cohere");
|
|
|
|
regAccessKeyCommand(context, "Anthropic");
|
|
|
|
regAccessKeyCommand(context, "Replicate");
|
|
|
|
regAccessKeyCommand(context, "HuggingFace");
|
|
|
|
regAccessKeyCommand(context, "TogetherAI");
|
|
|
|
regAccessKeyCommand(context, "OpenRouter");
|
|
|
|
regAccessKeyCommand(context, "VertexAI");
|
|
|
|
regAccessKeyCommand(context, "AI21");
|
|
|
|
regAccessKeyCommand(context, "BaseTen");
|
|
|
|
regAccessKeyCommand(context, "Azure");
|
|
|
|
regAccessKeyCommand(context, "SageMaker");
|
|
|
|
regAccessKeyCommand(context, "Bedrock");
|
|
|
|
regAccessKeyCommand(context, "DevChat");
|
2023-05-31 16:10:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export function registerStatusBarItemClickCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devcaht.onStatusBarClick', async () => {
|
|
|
|
await vscode.commands.executeCommand('devchat-view.focus');
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-05-31 16:10:53 +08:00
|
|
|
const topicDeleteCallback = async (item: TopicTreeItem) => {
|
|
|
|
const confirm = 'Delete';
|
|
|
|
const label = typeof item.label === 'string' ? item.label : item.label!.label;
|
|
|
|
const truncatedLabel = label.substring(0, 20) + (label.length > 20 ? '...' : '');
|
|
|
|
const result = await vscode.window.showWarningMessage(
|
|
|
|
`Are you sure you want to delete the topic "${truncatedLabel}"?`,
|
|
|
|
{ modal: true },
|
2023-07-17 18:56:56 +08:00
|
|
|
confirm
|
2023-05-31 16:10:53 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
if (result === confirm) {
|
|
|
|
TopicManager.getInstance().deleteTopic(item.id);
|
|
|
|
}
|
|
|
|
};
|
2023-09-13 10:08:16 +08:00
|
|
|
|
2023-05-31 16:10:53 +08:00
|
|
|
|
2023-05-31 16:10:53 +08:00
|
|
|
export function regTopicDeleteCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
2023-05-31 16:10:53 +08:00
|
|
|
vscode.commands.registerCommand('devchat-topicview.deleteTopic', topicDeleteCallback)
|
2023-05-31 16:10:53 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function regAddTopicCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat-topicview.addTopic', () => {
|
|
|
|
const topic = TopicManager.getInstance().createTopic();
|
|
|
|
TopicManager.getInstance().setCurrentTopic(topic.topicId);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function regDeleteSelectTopicCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat-topicview.deleteSelectedTopic', () => {
|
|
|
|
const selectedItem = TopicTreeDataProvider.getInstance().selectedItem;
|
|
|
|
if (selectedItem) {
|
2023-05-31 16:10:53 +08:00
|
|
|
topicDeleteCallback(selectedItem);
|
2023-05-31 16:10:53 +08:00
|
|
|
} else {
|
|
|
|
vscode.window.showErrorMessage('No item selected');
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function regSelectTopicCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat-topicview.selectTopic', (item: TopicTreeItem) => {
|
|
|
|
TopicTreeDataProvider.getInstance().setSelectedItem(item);
|
|
|
|
TopicManager.getInstance().setCurrentTopic(item.id);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function regReloadTopicCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
2023-05-31 16:10:53 +08:00
|
|
|
vscode.commands.registerCommand('devchat-topicview.reloadTopic', async () => {
|
2023-05-31 16:10:53 +08:00
|
|
|
TopicManager.getInstance().loadTopics();
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-07-06 07:42:44 +08:00
|
|
|
export function regPythonPathCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat.PythonPath', async () => {
|
|
|
|
const pythonPath = await vscode.window.showInputBox({
|
|
|
|
title: "Set Python Path",
|
|
|
|
placeHolder: "Set Python Path"
|
|
|
|
}) ?? '';
|
|
|
|
|
|
|
|
if (pythonPath) {
|
|
|
|
vscode.workspace.getConfiguration("DevChat").update("PythonPath", pythonPath, vscode.ConfigurationTarget.Global);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-05-31 16:10:53 +08:00
|
|
|
export function regApplyDiffResultCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
2023-05-31 16:10:53 +08:00
|
|
|
vscode.commands.registerCommand('devchat.applyDiffResult', async () => {
|
2023-05-31 16:10:53 +08:00
|
|
|
const activeEditor = vscode.window.activeTextEditor;
|
|
|
|
const fileName = activeEditor!.document.fileName;
|
|
|
|
|
|
|
|
const [leftUri, rightUri] = FilePairManager.getInstance().findPair(fileName) || [undefined, undefined];
|
|
|
|
if (leftUri && rightUri) {
|
|
|
|
// 获取对比的两个文件
|
|
|
|
const leftDoc = await vscode.workspace.openTextDocument(leftUri);
|
|
|
|
const rightDoc = await vscode.workspace.openTextDocument(rightUri);
|
|
|
|
|
|
|
|
// 将右边文档的内容替换到左边文档
|
|
|
|
const leftEditor = await vscode.window.showTextDocument(leftDoc);
|
|
|
|
await leftEditor.edit(editBuilder => {
|
|
|
|
const fullRange = new vscode.Range(0, 0, leftDoc.lineCount, 0);
|
|
|
|
editBuilder.replace(fullRange, rightDoc.getText());
|
|
|
|
});
|
|
|
|
|
|
|
|
// 保存左边文档
|
|
|
|
await leftDoc.save();
|
|
|
|
} else {
|
|
|
|
vscode.window.showErrorMessage('No file to apply diff result.');
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-07-24 00:11:56 +08:00
|
|
|
export function TestDevChatCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat.', async () => {
|
|
|
|
TopicManager.getInstance().loadTopics();
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
|
|
|
|
|
|
|
|
export function registerAskCodeIndexStartCommand(context: vscode.ExtensionContext) {
|
|
|
|
let disposable = vscode.commands.registerCommand('DevChat.AskCodeIndexStart', async () => {
|
2023-08-24 10:45:51 +08:00
|
|
|
if (!FT("ask-code")) {
|
|
|
|
UiUtilWrapper.showErrorMessage("This command is a beta version command and has not been released yet.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
const progressBar = new ProgressBar();
|
|
|
|
progressBar.init();
|
2023-08-30 22:57:51 +08:00
|
|
|
logger.channel()?.show();
|
2023-08-21 11:52:00 +08:00
|
|
|
|
|
|
|
progressBar.update("Index source code files for ask codebase ...", 0);
|
|
|
|
|
|
|
|
const config = getConfig();
|
2023-08-24 10:45:51 +08:00
|
|
|
let pythonVirtualEnv: any = config.pythonVirtualEnv;
|
2023-08-21 11:52:00 +08:00
|
|
|
const supportedFileTypes = config.supportedFileTypes;
|
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
updateIndexingStatus("started");
|
|
|
|
|
2023-08-24 10:45:51 +08:00
|
|
|
if (pythonVirtualEnv) {
|
|
|
|
// check whether pythonVirtualEnv is stisfy the requirement version
|
|
|
|
const devchatAskVersion = getPackageVersion(pythonVirtualEnv, "devchat-ask");
|
|
|
|
|
|
|
|
let requireAskVersion = "0.0.8";
|
|
|
|
if (FT("ask-code-summary")) {
|
|
|
|
requireAskVersion = "0.0.10";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!devchatAskVersion || devchatAskVersion < requireAskVersion) {
|
|
|
|
logger.channel()?.info(`The version of devchat-ask is ${devchatAskVersion}`);
|
|
|
|
pythonVirtualEnv = undefined;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-30 22:57:51 +08:00
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
if (!pythonVirtualEnv) {
|
2023-08-29 15:29:27 +08:00
|
|
|
progressBar.update("Installing devchat-ask. See OUTPUT for progress...", 0);
|
2023-08-21 11:52:00 +08:00
|
|
|
await installAskCode(supportedFileTypes, progressBar, indexCode);
|
2023-08-21 11:52:00 +08:00
|
|
|
} else {
|
2023-08-29 15:29:27 +08:00
|
|
|
progressBar.update("Index source files. See OUTPUT for progress...", 0);
|
2023-08-21 11:52:00 +08:00
|
|
|
await indexCode(pythonVirtualEnv, supportedFileTypes, progressBar);
|
2023-08-21 11:52:00 +08:00
|
|
|
}
|
2023-08-21 11:52:00 +08:00
|
|
|
|
|
|
|
updateIndexingStatus("stopped");
|
2023-08-21 11:52:00 +08:00
|
|
|
});
|
|
|
|
context.subscriptions.push(disposable);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getConfig() {
|
|
|
|
return {
|
|
|
|
pythonVirtualEnv: vscode.workspace.getConfiguration('DevChat').get('PythonVirtualEnv'),
|
|
|
|
supportedFileTypes: vscode.workspace.getConfiguration('DevChat.askcode').get('supportedFileTypes'),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
|
|
|
|
async function installAskCode(supportedFileTypes, progressBar: any, callback: Function) {
|
|
|
|
const pythonEnvPath : string = await installAskCodeFun();
|
|
|
|
if (!pythonEnvPath) {
|
|
|
|
logger.channel()?.error(`Installation failed!`);
|
|
|
|
logger.channel()?.show();
|
2023-08-21 11:52:00 +08:00
|
|
|
return;
|
2023-08-21 11:52:00 +08:00
|
|
|
}
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
UiUtilWrapper.updateConfiguration("DevChat", "PythonVirtualEnv", pythonEnvPath.trim());
|
2023-08-21 11:52:00 +08:00
|
|
|
logger.channel()?.info(`Installation finished.`);
|
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
// Execute the callback function after the installation is finished
|
|
|
|
await callback(pythonEnvPath, supportedFileTypes, progressBar);
|
2023-08-21 11:52:00 +08:00
|
|
|
}
|
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
async function indexCode(pythonVirtualEnv, supportedFileTypes, progressBar: any) {
|
2023-08-21 11:52:00 +08:00
|
|
|
let envs = {};
|
|
|
|
|
2023-09-13 10:08:16 +08:00
|
|
|
const llmModelData = await ApiKeyManager.llmModel();
|
|
|
|
if (!llmModelData) {
|
|
|
|
logger.channel()?.error('No valid llm model is selected!');
|
|
|
|
logger.channel()?.show();
|
|
|
|
|
|
|
|
progressBar.endWithError("No valid llm model is selected!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let openaiApiKey = llmModelData.api_key;
|
2023-08-21 11:52:00 +08:00
|
|
|
if (!openaiApiKey) {
|
|
|
|
logger.channel()?.error('The OpenAI key is invalid!');
|
|
|
|
logger.channel()?.show();
|
2023-08-21 11:52:00 +08:00
|
|
|
|
|
|
|
progressBar.endWithError("The OpenAI key is invalid!");
|
2023-08-21 11:52:00 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
envs['OPENAI_API_KEY'] = openaiApiKey;
|
|
|
|
|
2023-09-13 10:08:16 +08:00
|
|
|
const openAiApiBase = llmModelData.api_base;
|
2023-08-21 11:52:00 +08:00
|
|
|
if (openAiApiBase) {
|
|
|
|
envs['OPENAI_API_BASE'] = openAiApiBase;
|
|
|
|
}
|
|
|
|
|
|
|
|
const workspaceDir = UiUtilWrapper.workspaceFoldersFirstPath();
|
|
|
|
|
|
|
|
const command = pythonVirtualEnv.trim();
|
|
|
|
const args = [UiUtilWrapper.extensionPath() + "/tools/askcode_index_query.py", "index", ".", supportedFileTypes];
|
|
|
|
const options = { env: envs, cwd: workspaceDir };
|
|
|
|
|
|
|
|
indexProcess = new CommandRun();
|
|
|
|
const result = await indexProcess.spawnAsync(command, args, options, (data) => {
|
|
|
|
if (data.includes('Skip file:')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
logger.channel()?.info(`${data}`);
|
|
|
|
}, (data) => {
|
|
|
|
if (data.includes('Skip file:')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
logger.channel()?.info(`${data}`);
|
|
|
|
}, undefined, undefined);
|
|
|
|
|
|
|
|
if (result.exitCode !== 0) {
|
|
|
|
if (result.exitCode === null) {
|
|
|
|
logger.channel()?.info(`Indexing stopped!`);
|
2023-08-21 11:52:00 +08:00
|
|
|
progressBar.endWithError(`Indexing stopped!`);
|
2023-08-21 11:52:00 +08:00
|
|
|
} else {
|
|
|
|
logger.channel()?.error(`Indexing failed: ${result.stderr}`);
|
|
|
|
logger.channel()?.show();
|
2023-08-21 11:52:00 +08:00
|
|
|
progressBar.endWithError(`Indexing failed: ${result.stderr}`);
|
2023-08-21 11:52:00 +08:00
|
|
|
}
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
updateLastModifyTime();
|
2023-08-21 11:52:00 +08:00
|
|
|
logger.channel()?.info(`index finished.`);
|
2023-08-21 11:52:00 +08:00
|
|
|
|
|
|
|
progressBar.update("Indexing finished.");
|
|
|
|
progressBar.end();
|
2023-08-21 11:52:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function registerAskCodeIndexStopCommand(context: vscode.ExtensionContext) {
|
|
|
|
let disposable = vscode.commands.registerCommand('DevChat.AskCodeIndexStop', async () => {
|
2023-08-24 10:45:51 +08:00
|
|
|
if (!FT("ask-code")) {
|
|
|
|
UiUtilWrapper.showErrorMessage("This command is a beta version command and has not been released yet.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
if (indexProcess) {
|
|
|
|
indexProcess.stop();
|
|
|
|
indexProcess = null;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
context.subscriptions.push(disposable);
|
|
|
|
}
|
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
let summaryIndexTargetDir: string | undefined = undefined;
|
2023-08-24 10:45:51 +08:00
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
export async function askcodeSummaryIndex(targetDir: string|undefined) {
|
|
|
|
if (!FT("ask-code-summary")) {
|
|
|
|
UiUtilWrapper.showErrorMessage("This command is a beta version command and has not been released yet.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
summaryIndexTargetDir = targetDir;
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
const progressBar = new ProgressBar();
|
|
|
|
progressBar.init();
|
|
|
|
logger.channel()?.show();
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
progressBar.update("Index source code files for ask codebase summary...", 0);
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
const config = getConfig();
|
|
|
|
let pythonVirtualEnv: any = config.pythonVirtualEnv;
|
|
|
|
const supportedFileTypes = config.supportedFileTypes;
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
updateIndexingStatus("started");
|
2023-08-24 10:45:51 +08:00
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
if (pythonVirtualEnv) {
|
|
|
|
// check whether pythonVirtualEnv is stisfy the requirement version
|
|
|
|
const devchatAskVersion = getPackageVersion(pythonVirtualEnv, "devchat-ask");
|
|
|
|
|
|
|
|
let requireAskVersion = "0.0.8";
|
|
|
|
if (FT("ask-code-summary")) {
|
|
|
|
requireAskVersion = "0.0.10";
|
2023-08-24 10:45:51 +08:00
|
|
|
}
|
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
if (!devchatAskVersion || devchatAskVersion < requireAskVersion) {
|
|
|
|
logger.channel()?.info(`The version of devchat-ask is ${devchatAskVersion}`);
|
|
|
|
pythonVirtualEnv = undefined;
|
|
|
|
}
|
|
|
|
}
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
if (!pythonVirtualEnv) {
|
|
|
|
progressBar.update("Installing devchat-ask. See OUTPUT for progress...", 0);
|
|
|
|
await installAskCode(supportedFileTypes, progressBar, indexCodeSummary);
|
|
|
|
} else {
|
|
|
|
progressBar.update("Index source files. See OUTPUT for progress...", 0);
|
|
|
|
await indexCodeSummary(pythonVirtualEnv, supportedFileTypes, progressBar);
|
|
|
|
}
|
|
|
|
|
|
|
|
updateIndexingStatus("stopped");
|
|
|
|
}
|
|
|
|
|
|
|
|
export function registerAskCodeSummaryIndexStartCommand(context: vscode.ExtensionContext) {
|
|
|
|
let disposable = vscode.commands.registerCommand('DevChat.AskCodeSummaryIndexStart', async () => {
|
|
|
|
askcodeSummaryIndex("*");
|
2023-08-21 11:52:00 +08:00
|
|
|
});
|
|
|
|
context.subscriptions.push(disposable);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function indexCodeSummary(pythonVirtualEnv, supportedFileTypes, progressBar: any) {
|
|
|
|
let envs = {};
|
|
|
|
|
2023-09-13 10:08:16 +08:00
|
|
|
const llmModelData = await ApiKeyManager.llmModel();
|
|
|
|
if (!llmModelData) {
|
|
|
|
logger.channel()?.error('No valid llm model is selected!');
|
|
|
|
logger.channel()?.show();
|
|
|
|
|
|
|
|
progressBar.endWithError("No valid llm model is selected!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let openaiApiKey = llmModelData.api_key;
|
2023-08-21 11:52:00 +08:00
|
|
|
if (!openaiApiKey) {
|
|
|
|
logger.channel()?.error('The OpenAI key is invalid!');
|
|
|
|
logger.channel()?.show();
|
|
|
|
|
2023-09-13 10:08:16 +08:00
|
|
|
progressBar.endWithError("The OpenAI key is invalid!");
|
2023-08-21 11:52:00 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
envs['OPENAI_API_KEY'] = openaiApiKey;
|
|
|
|
|
2023-09-13 10:08:16 +08:00
|
|
|
const openAiApiBase = llmModelData.api_base;
|
2023-08-21 11:52:00 +08:00
|
|
|
if (openAiApiBase) {
|
|
|
|
envs['OPENAI_API_BASE'] = openAiApiBase;
|
|
|
|
}
|
|
|
|
|
|
|
|
const workspaceDir = UiUtilWrapper.workspaceFoldersFirstPath();
|
|
|
|
|
|
|
|
const command = pythonVirtualEnv.trim();
|
2023-08-31 17:52:06 +08:00
|
|
|
const args = [UiUtilWrapper.extensionPath() + "/tools/askcode_summary_index.py", "index", supportedFileTypes, summaryIndexTargetDir];
|
2023-08-21 11:52:00 +08:00
|
|
|
const options = { env: envs, cwd: workspaceDir };
|
|
|
|
|
|
|
|
summaryIndexProcess = new CommandRun();
|
|
|
|
const result = await summaryIndexProcess.spawnAsync(command, args, options, (data) => {
|
|
|
|
if (data.includes('Skip file:')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
logger.channel()?.info(`${data}`);
|
|
|
|
}, (data) => {
|
|
|
|
if (data.includes('Skip file:')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
logger.channel()?.info(`${data}`);
|
|
|
|
}, undefined, undefined);
|
|
|
|
|
|
|
|
if (result.exitCode !== 0) {
|
|
|
|
if (result.exitCode === null) {
|
|
|
|
logger.channel()?.info(`Indexing stopped!`);
|
|
|
|
progressBar.endWithError(`Indexing stopped!`);
|
|
|
|
} else {
|
|
|
|
logger.channel()?.error(`Indexing failed: ${result.stderr}`);
|
|
|
|
logger.channel()?.show();
|
|
|
|
progressBar.endWithError(`Indexing failed: ${result.stderr}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
updateLastModifyTime();
|
|
|
|
logger.channel()?.info(`index finished.`);
|
|
|
|
|
|
|
|
progressBar.update("Indexing finished.");
|
|
|
|
progressBar.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
export function registerAskCodeSummaryIndexStopCommand(context: vscode.ExtensionContext) {
|
|
|
|
let disposable = vscode.commands.registerCommand('DevChat.AskCodeIndexSummaryStop', async () => {
|
2023-08-24 10:45:51 +08:00
|
|
|
if (!FT("ask-code-summary")) {
|
|
|
|
UiUtilWrapper.showErrorMessage("This command is a beta version command and has not been released yet.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (summaryIndexProcess) {
|
2023-08-21 11:52:00 +08:00
|
|
|
summaryIndexProcess.stop();
|
|
|
|
summaryIndexProcess = null;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
context.subscriptions.push(disposable);
|
|
|
|
}
|
|
|
|
|
2023-08-30 16:39:47 +08:00
|
|
|
|
|
|
|
export function registerInstallCommandsCommand(context: vscode.ExtensionContext) {
|
|
|
|
let disposable = vscode.commands.registerCommand('DevChat.InstallCommands', async () => {
|
2023-08-30 17:03:22 +08:00
|
|
|
const devchat = new DevChat();
|
|
|
|
await devchat.updateSysCommand();
|
2023-08-30 16:39:47 +08:00
|
|
|
|
2023-08-30 17:03:22 +08:00
|
|
|
sendCommandListByDevChatRun();
|
2023-08-30 16:39:47 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
context.subscriptions.push(disposable);
|
|
|
|
}
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
export async function addSummaryContextFun(fsPath: string ) {
|
|
|
|
if (!FT("ask-code-summary")) {
|
|
|
|
UiUtilWrapper.showErrorMessage("This command is a beta version command and has not been released yet.");
|
|
|
|
return;
|
|
|
|
}
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-08-31 17:52:06 +08:00
|
|
|
const workspaceDir = UiUtilWrapper.workspaceFoldersFirstPath();
|
|
|
|
if (!workspaceDir) {
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
// check whether workspaceDir/.chat/.summary.json文件存在
|
|
|
|
if (!fs.existsSync(path.join(workspaceDir, '.chat', '.summary.json'))) {
|
|
|
|
logger.channel()?.info(`You should index this workspace first.`);
|
|
|
|
logger.channel()?.show();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const config = getConfig();
|
|
|
|
const pythonVirtualEnv: any = config.pythonVirtualEnv;
|
|
|
|
|
|
|
|
const tempDir = await createTempSubdirectory('devchat/context');
|
|
|
|
const summaryFile = path.join(tempDir, 'summary.txt');
|
|
|
|
|
|
|
|
const summaryArgs = [pythonVirtualEnv, UiUtilWrapper.extensionPath() + "/tools/askcode_summary_index.py", "desc", fsPath];
|
|
|
|
const result = await runCommandStringArrayAndWriteOutput(summaryArgs, summaryFile);
|
|
|
|
logger.channel()?.info(` exit code:`, result.exitCode);
|
|
|
|
|
|
|
|
logger.channel()?.debug(` stdout:`, result.stdout);
|
|
|
|
logger.channel()?.debug(` stderr:`, result.stderr);
|
|
|
|
MessageHandler.sendMessage(ExtensionContextHolder.provider?.view()!, { command: 'appendContext', context: `[context|${summaryFile}]` });
|
|
|
|
}
|
|
|
|
export function registerAddSummaryContextCommand(context: vscode.ExtensionContext) {
|
|
|
|
const callback = async (uri: { fsPath: any; }) => {
|
|
|
|
addSummaryContextFun(uri.fsPath);
|
2023-08-21 11:52:00 +08:00
|
|
|
};
|
|
|
|
context.subscriptions.push(vscode.commands.registerCommand('devchat.addSummaryContext', callback));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-05-05 21:27:40 +08:00
|
|
|
export {
|
2023-05-31 16:10:53 +08:00
|
|
|
registerOpenChatPanelCommand,
|
|
|
|
registerAddContextCommand,
|
|
|
|
registerAskForCodeCommand,
|
|
|
|
registerAskForFileCommand,
|
2023-05-05 21:27:40 +08:00
|
|
|
};
|