mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-02 08:15:56 +01:00
Fix skill delete behaviour (#298814)
This commit is contained in:
@@ -35,7 +35,7 @@ import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contex
|
||||
import { ChatConfiguration } from '../../common/constants.js';
|
||||
import { IFileService } from '../../../../../platform/files/common/files.js';
|
||||
import { IDialogService } from '../../../../../platform/dialogs/common/dialogs.js';
|
||||
import { basename } from '../../../../../base/common/resources.js';
|
||||
import { basename, dirname } from '../../../../../base/common/resources.js';
|
||||
import { Schemas } from '../../../../../base/common/network.js';
|
||||
import { isWindows, isMacintosh } from '../../../../../base/common/platform.js';
|
||||
|
||||
@@ -119,6 +119,16 @@ function extractStorage(context: AICustomizationContext): PromptsStorage | undef
|
||||
return context.storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts prompt type from context.
|
||||
*/
|
||||
function extractPromptType(context: AICustomizationContext): PromptsType | undefined {
|
||||
if (URI.isUri(context) || typeof context === 'string') {
|
||||
return undefined;
|
||||
}
|
||||
return context.promptType;
|
||||
}
|
||||
|
||||
// Open file action
|
||||
const OPEN_AI_CUSTOMIZATION_MGMT_FILE_ID = 'aiCustomizationManagement.openFile';
|
||||
registerAction2(class extends Action2 {
|
||||
@@ -193,8 +203,11 @@ registerAction2(class extends Action2 {
|
||||
const dialogService = accessor.get(IDialogService);
|
||||
|
||||
const uri = extractURI(context);
|
||||
const fileName = basename(uri);
|
||||
const storage = extractStorage(context);
|
||||
const promptType = extractPromptType(context);
|
||||
const isSkill = promptType === PromptsType.skill;
|
||||
// For skills, use the parent folder name since skills are structured as <skillname>/SKILL.md.
|
||||
const fileName = isSkill ? basename(dirname(uri)) : basename(uri);
|
||||
|
||||
// Extension and plugin files cannot be deleted
|
||||
if (storage === PromptsStorage.extension || storage === PromptsStorage.plugin) {
|
||||
@@ -206,15 +219,21 @@ registerAction2(class extends Action2 {
|
||||
}
|
||||
|
||||
// Confirm deletion
|
||||
const message = isSkill
|
||||
? localize('confirmDeleteSkill', "Are you sure you want to delete skill '{0}' and its folder?", fileName)
|
||||
: localize('confirmDelete', "Are you sure you want to delete '{0}'?", fileName);
|
||||
const confirmation = await dialogService.confirm({
|
||||
message: localize('confirmDelete', "Are you sure you want to delete '{0}'?", fileName),
|
||||
message,
|
||||
detail: localize('confirmDeleteDetail', "This action cannot be undone."),
|
||||
primaryButton: localize('delete', "Delete"),
|
||||
type: 'warning',
|
||||
});
|
||||
|
||||
if (confirmation.confirmed) {
|
||||
await fileService.del(uri, { useTrash: true });
|
||||
// For skills, delete the parent folder (e.g. .github/skills/my-skill/)
|
||||
// since each skill is a folder containing SKILL.md.
|
||||
const deleteTarget = isSkill ? dirname(uri) : uri;
|
||||
await fileService.del(deleteTarget, { useTrash: true, recursive: isSkill });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import { URI } from '../../../../../../base/common/uri.js';
|
||||
import { Codicon } from '../../../../../../base/common/codicons.js';
|
||||
import { ThemeIcon } from '../../../../../../base/common/themables.js';
|
||||
import { AgentFileType, IExtensionPromptPath, IPromptPath, IPromptsService, PromptsStorage } from '../../../common/promptSyntax/service/promptsService.js';
|
||||
import { dirname, extUri, joinPath } from '../../../../../../base/common/resources.js';
|
||||
import { basename, dirname, extUri, joinPath } from '../../../../../../base/common/resources.js';
|
||||
import { DisposableStore } from '../../../../../../base/common/lifecycle.js';
|
||||
import { IFileService } from '../../../../../../platform/files/common/files.js';
|
||||
import { IOpenerService } from '../../../../../../platform/opener/common/opener.js';
|
||||
@@ -651,16 +651,23 @@ export class PromptFilePickers {
|
||||
// don't close the main prompt selection dialog by the confirmation dialog
|
||||
return await this.keepQuickPickOpen(quickPick, async () => {
|
||||
|
||||
const filename = getCleanPromptName(value);
|
||||
const message = localize('commands.prompts.use.select-dialog.delete-prompt.confirm.message', "Are you sure you want to delete '{0}'?", filename);
|
||||
const isSkill = options.type === PromptsType.skill;
|
||||
// For skills, use the parent folder name as the display name
|
||||
// since skills are structured as <skillname>/SKILL.md.
|
||||
const filename = isSkill ? basename(dirname(value)) : item.label;
|
||||
const message = isSkill
|
||||
? localize('commands.prompts.use.select-dialog.delete-skill.confirm.message', "Are you sure you want to delete skill '{0}' and its folder?", filename)
|
||||
: localize('commands.prompts.use.select-dialog.delete-prompt.confirm.message', "Are you sure you want to delete '{0}'?", filename);
|
||||
const { confirmed } = await this._dialogService.confirm({ message });
|
||||
// if prompt deletion was not confirmed, nothing to do
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// prompt deletion was confirmed so delete the prompt file
|
||||
await this._fileService.del(value);
|
||||
// For skills, delete the parent folder (e.g. .github/skills/my-skill/)
|
||||
// since each skill is a folder containing SKILL.md.
|
||||
const deleteTarget = isSkill ? dirname(value) : value;
|
||||
await this._fileService.del(deleteTarget, { recursive: isSkill, useTrash: true });
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user