diff --git a/package.json b/package.json index 4c27aec..c84b33e 100644 --- a/package.json +++ b/package.json @@ -296,6 +296,11 @@ "command": "DevChat.AskCodeIndexSummaryStop", "title": "Stop AskCode Summary Index", "category": "DevChat" + }, + { + "command": "DevChat.InstallCommands", + "title": "Install slash commands", + "category": "DevChat" } ], "menus": { diff --git a/src/contributes/commands.ts b/src/contributes/commands.ts index c82696a..d2c2460 100644 --- a/src/contributes/commands.ts +++ b/src/contributes/commands.ts @@ -20,6 +20,9 @@ import { MessageHandler } from '../handler/messageHandler'; import { FT } from '../util/feature_flags/feature_toggles'; import { getPackageVersion } from '../util/python_installer/pip_package_version'; +import { exec } from 'child_process'; +import { sendCommandListByDevChatRun } from '../handler/regCommandList'; + let indexProcess: CommandRun | null = null; let summaryIndexProcess: CommandRun | null = null; @@ -500,6 +503,49 @@ export function registerAskCodeSummaryIndexStopCommand(context: vscode.Extension context.subscriptions.push(disposable); } + +export function registerInstallCommandsCommand(context: vscode.ExtensionContext) { + let disposable = vscode.commands.registerCommand('DevChat.InstallCommands', async () => { + // step 1: find User Home Dir + const homeDir = process.env.HOME || process.env.USERPROFILE; + if (!homeDir) { + logger.channel()?.error(`Error: No valid home directory found.`); + logger.channel()?.show(); + return; + } + + // step 2: create ensure {User Home Dir}/.chat/workflows/ exists + const targetDir = path.join(homeDir, '.chat', 'workflows'); + fs.mkdirSync(targetDir, { recursive: true }); + + const sysDir = path.join(targetDir, 'sys'); + if (fs.existsSync(sysDir)) { + // step 3: if sys exists, then git pull + logger.channel()?.info(`Git pull from sys...`); + exec('git pull', { cwd: sysDir }, (error, stdout, stderr) => { + if (error) { + logger.channel()?.error(`Error pulling git repo: ${error}`); + } else { + logger.channel()?.info(`Git pull successful: ${stdout}`); + sendCommandListByDevChatRun(); + } + }); + } else { + // step 4: if sys not exists, then git clone + logger.channel()?.info(`Git clone to sys...`); + exec('git clone https://github.com/devchat-ai/workflows.git sys', { cwd: targetDir }, (error, stdout, stderr) => { + if (error) { + logger.channel()?.error(`Error cloning git repo: ${error}`); + } else { + logger.channel()?.info(`Git clone successful: ${stdout}`); + sendCommandListByDevChatRun(); + } + }); + } + }); + + context.subscriptions.push(disposable); +} export function registerAddSummaryContextCommand(context: vscode.ExtensionContext) { const callback = async (uri: { fsPath: any; }) => { if (!FT("ask-code-summary")) { diff --git a/src/extension.ts b/src/extension.ts index 853b6a8..c531841 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -20,6 +20,7 @@ import { registerAskCodeSummaryIndexStartCommand, registerAskCodeSummaryIndexStopCommand, registerAddSummaryContextCommand, + registerInstallCommandsCommand, } from './contributes/commands'; import { regLanguageContext } from './contributes/context'; import { regDevChatView, regTopicView } from './contributes/views'; @@ -52,6 +53,8 @@ function activate(context: vscode.ExtensionContext) { registerAskForFileCommand(context); registerStatusBarItemClickCommand(context); + registerInstallCommandsCommand(context); + createStatusBarItem(context); if (FT("ask-code")) { createAskCodeStatusBarItem(context); diff --git a/src/handler/regCommandList.ts b/src/handler/regCommandList.ts index 3185008..e59f8a9 100644 --- a/src/handler/regCommandList.ts +++ b/src/handler/regCommandList.ts @@ -21,9 +21,13 @@ export async function regCommandList(message: any, panel: vscode.WebviewPanel|vs return; } +let existPannel: vscode.WebviewPanel|vscode.WebviewView|undefined = undefined; + regInMessage({command: 'regCommandList'}); regOutMessage({command: 'regCommandList', result: [{name: '', pattern: '', description: ''}]}); export async function regCommandListByDevChatRun(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise { + existPannel = panel; + const commandList = await CommandManager.getInstance().getCommandListByDevChatRun(); const commandCovertedList = commandList.map(command => { if (command.args > 0) { @@ -38,3 +42,9 @@ export async function regCommandListByDevChatRun(message: any, panel: vscode.Web return; } +export async function sendCommandListByDevChatRun() { + if (existPannel) { + regCommandListByDevChatRun({}, existPannel!); + } +} + diff --git a/src/panel/statusBarView.ts b/src/panel/statusBarView.ts index 0c472ee..1f78d40 100644 --- a/src/panel/statusBarView.ts +++ b/src/panel/statusBarView.ts @@ -8,6 +8,9 @@ import { ProgressBar } from '../util/progressBar'; export function createStatusBarItem(context: vscode.ExtensionContext): vscode.StatusBarItem { const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100); + // execute command: DevChat.InstallCommands + vscode.commands.executeCommand('DevChat.InstallCommands'); + // Set the status bar item properties statusBarItem.text = `$(warning)DevChat`; statusBarItem.tooltip = 'DevChat is checking ..., please wait'; diff --git a/src/views/components/InputMessage/index.tsx b/src/views/components/InputMessage/index.tsx index 05460de..6c9ce88 100644 --- a/src/views/components/InputMessage/index.tsx +++ b/src/views/components/InputMessage/index.tsx @@ -185,6 +185,9 @@ const InputMessage = observer((props: any) => { useEffect(() => { input.fetchContextMenus().then(); input.fetchCommandMenus().then(); + messageUtil.registerHandler('regCommandList', (message: { result: object[]}) => { + input.updateCommands(message.result); + }); messageUtil.registerHandler('appendContext', (message: { command: string; context: string }) => { // context is a temp file path const match = /\|([^]+?)\]/.exec(message.context); diff --git a/src/views/stores/InputStore.ts b/src/views/stores/InputStore.ts index 07353f3..810b294 100644 --- a/src/views/stores/InputStore.ts +++ b/src/views/stores/InputStore.ts @@ -21,20 +21,6 @@ const regContextMenus = async () => { }); }; - -const regCommandMenus = async () => { - return new Promise((resolve, reject) => { - try { - messageUtil.sendMessage({ command: 'regCommandList' }); - messageUtil.registerHandler('regCommandList', (message: { result: Item[] }) => { - resolve(message.result); - }); - } catch (e) { - reject(e); - } - }); -}; - export const ChatContext = types.model({ file: types.maybe(types.string), path: types.maybe(types.string), @@ -89,6 +75,11 @@ export const InputStore = types setCurrentMenuIndex(index: number) { self.currentMenuIndex = index; }, + updateCommands(items) { + self.commandMenus.clear(); + self.commandMenus.push(...items); + self.commandMenus.push({ name: 'help', description: 'View the DevChat documentation.', pattern: 'help' }); + }, fetchContextMenus: flow(function* () { try { const items = yield regContextMenus(); @@ -97,15 +88,24 @@ export const InputStore = types console.error("Failed to fetch context menus", error); } }), + fetchCommandMenus: flow(function* () { - try { - const items = yield regCommandMenus(); - self.commandMenus.push(...items); - self.commandMenus.push({ name: 'help', description: 'View the DevChat documentation.', pattern: 'help' }); - } catch (error) { - console.error("Failed to fetch command menus", error); - } - }) + const regCommandMenus = async () => { + return new Promise((resolve, reject) => { + try { + messageUtil.sendMessage({ command: 'regCommandList' }); + } catch (e) { + reject(e); + } + }); + }; + + try { + yield regCommandMenus(); + } catch (error) { + console.error("Failed to fetch command menus", error); + } + }) }));