Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand All @@ -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 });
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
});

Expand Down
Loading