diff --git a/clients/vscode/package.json b/clients/vscode/package.json index 254c493a871e..51bf66b4ddde 100644 --- a/clients/vscode/package.json +++ b/clients/vscode/package.json @@ -270,6 +270,11 @@ "Automatic trigger when you stop typing", "Manual trigger by pressing `Alt + \\`" ] + }, + "chatEdit.history": { + "type": "integer", + "default": 20, + "description": "The maximum number of recently used commands to keep. Set to 0 to disable recording." } } } diff --git a/clients/vscode/src/Commands.ts b/clients/vscode/src/Commands.ts index 55e16da2b42e..d7e7587055b2 100644 --- a/clients/vscode/src/Commands.ts +++ b/clients/vscode/src/Commands.ts @@ -262,21 +262,21 @@ export class Commands { }, }, }; - const recentlyCommand = this.config.chatEditRecentlyCommand; + //ensure max length + const recentlyCommand = this.config.chatEditRecentlyCommand.slice(0, this.config.chatEditHistory); const suggestedCommand: ChatEditCommand[] = []; const quickPick = window.createQuickPick(); + const updateQuickPickList = () => { const input = quickPick.value; const list: (QuickPickItem & { value: string })[] = []; list.push( - ...suggestedCommand.map((item) => { - return { - label: item.label, - value: item.command, - iconPath: item.source === "preset" ? new ThemeIcon("edit") : new ThemeIcon("spark"), - description: item.source === "preset" ? item.command : "Suggested", - }; - }), + ...suggestedCommand.map((item) => ({ + label: item.label, + value: item.command, + iconPath: item.source === "preset" ? new ThemeIcon("edit") : new ThemeIcon("spark"), + description: item.source === "preset" ? item.command : "Suggested", + })), ); if (list.length > 0) { list.push({ @@ -288,14 +288,17 @@ export class Commands { } const recentlyCommandToAdd = recentlyCommand.filter((item) => !list.find((i) => i.value === item)); list.push( - ...recentlyCommandToAdd.map((item) => { - return { - label: item, - value: item, - iconPath: new ThemeIcon("history"), - description: "History", - }; - }), + ...recentlyCommandToAdd.map((item) => ({ + label: item, + value: item, + iconPath: new ThemeIcon("history"), + description: "History", + buttons: [ + { + iconPath: new ThemeIcon("settings-remove"), + }, + ], + })), ); if (input.length > 0 && !list.find((i) => i.value === input)) { list.unshift({ @@ -308,12 +311,14 @@ export class Commands { } quickPick.items = list; }; + const fetchingSuggestedCommandCancellationTokenSource = new CancellationTokenSource(); this.client.chat.provideEditCommands( { location: editLocation }, { commands: suggestedCommand, callback: () => updateQuickPickList() }, fetchingSuggestedCommandCancellationTokenSource.token, ); + quickPick.placeholder = "Enter the command for editing"; quickPick.matchOnDescription = true; quickPick.onDidChangeValue(() => updateQuickPickList()); @@ -324,9 +329,11 @@ export class Commands { quickPick.hide(); const command = quickPick.selectedItems[0]?.value; if (command) { - this.config.chatEditRecentlyCommand = [command] + const updatedRecentlyCommand = [command] .concat(recentlyCommand.filter((item) => item !== command)) - .slice(0, 20); + .slice(0, this.config.chatEditHistory); + this.config.chatEditRecentlyCommand = updatedRecentlyCommand; + window.withProgress( { location: ProgressLocation.Notification, @@ -365,6 +372,20 @@ export class Commands { ); } }); + + quickPick.onDidTriggerItemButton((event) => { + const item = event.item; + const button = event.button; + if (button.iconPath instanceof ThemeIcon && button.iconPath.id === "settings-remove") { + const index = recentlyCommand.indexOf(item.value); + if (index !== -1) { + recentlyCommand.splice(index, 1); + this.config.chatEditRecentlyCommand = recentlyCommand; + updateQuickPickList(); + } + } + }); + quickPick.show(); }, "chat.edit.stop": async () => { diff --git a/clients/vscode/src/Config.ts b/clients/vscode/src/Config.ts index d69e3d8f6dba..01c34d6dab40 100644 --- a/clients/vscode/src/Config.ts +++ b/clients/vscode/src/Config.ts @@ -4,6 +4,7 @@ import { ClientProvidedConfig } from "tabby-agent"; interface AdvancedSettings { "inlineCompletion.triggerMode"?: "automatic" | "manual"; + "chatEdit.history"?: number; } export class Config extends EventEmitter { @@ -61,6 +62,27 @@ export class Config extends EventEmitter { } } + get chatEditHistory(): number { + const advancedSettings = this.workspace.get("settings.advanced", {}) as AdvancedSettings; + const numHistory = advancedSettings["chatEdit.history"] === undefined ? 20 : advancedSettings["chatEdit.history"]; + if (numHistory < 0) { + return 20; + } else if (numHistory === 0) { + return 0; + } else { + return numHistory; + } + } + + set chatEditHistory(value: number) { + if (value != this.chatEditHistory) { + const advancedSettings = this.workspace.get("settings.advanced", {}) as AdvancedSettings; + const updateValue = { ...advancedSettings, "chatEdit.history": value }; + this.workspace.update("settings.advanced", updateValue, ConfigurationTarget.Global); + this.emit("updated"); + } + } + get inlineCompletionEnabled(): boolean { return workspace.getConfiguration("editor").get("inlineSuggest.enabled", true); }