Skip to content

Commit 1e17b3b

Browse files
feat: add confirmation dialog and proper cleanup for marketplace mode removal (RooCodeInc#6136)
Co-authored-by: Daniel Riccio <[email protected]>
1 parent 3977bbc commit 1e17b3b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+861
-251
lines changed

src/core/config/CustomModesManager.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as vscode from "vscode"
22
import * as path from "path"
33
import * as fs from "fs/promises"
4+
import * as os from "os"
45

56
import * as yaml from "yaml"
67
import stripBom from "strip-bom"
@@ -501,7 +502,7 @@ export class CustomModesManager {
501502
await this.onUpdate()
502503
}
503504

504-
public async deleteCustomMode(slug: string): Promise<void> {
505+
public async deleteCustomMode(slug: string, fromMarketplace = false): Promise<void> {
505506
try {
506507
const settingsPath = await this.getCustomModesFilePath()
507508
const roomodesPath = await this.getWorkspaceRoomodes()
@@ -517,6 +518,9 @@ export class CustomModesManager {
517518
throw new Error(t("common:customModes.errors.modeNotFound"))
518519
}
519520

521+
// Determine which mode to use for rules folder path calculation
522+
const modeToDelete = projectMode || globalMode
523+
520524
await this.queueWrite(async () => {
521525
// Delete from project first if it exists there
522526
if (projectMode && roomodesPath) {
@@ -528,6 +532,11 @@ export class CustomModesManager {
528532
await this.updateModesInFile(settingsPath, (modes) => modes.filter((m) => m.slug !== slug))
529533
}
530534

535+
// Delete associated rules folder
536+
if (modeToDelete) {
537+
await this.deleteRulesFolder(slug, modeToDelete, fromMarketplace)
538+
}
539+
531540
// Clear cache when modes are deleted
532541
this.clearCache()
533542
await this.refreshMergedState()
@@ -538,6 +547,54 @@ export class CustomModesManager {
538547
}
539548
}
540549

550+
/**
551+
* Deletes the rules folder for a specific mode
552+
* @param slug - The mode slug
553+
* @param mode - The mode configuration to determine the scope
554+
*/
555+
private async deleteRulesFolder(slug: string, mode: ModeConfig, fromMarketplace = false): Promise<void> {
556+
try {
557+
// Determine the scope based on source (project or global)
558+
const scope = mode.source || "global"
559+
560+
// Determine the rules folder path
561+
let rulesFolderPath: string
562+
if (scope === "project") {
563+
const workspacePath = getWorkspacePath()
564+
if (workspacePath) {
565+
rulesFolderPath = path.join(workspacePath, ".roo", `rules-${slug}`)
566+
} else {
567+
return // No workspace, can't delete project rules
568+
}
569+
} else {
570+
// Global scope - use OS home directory
571+
const homeDir = os.homedir()
572+
rulesFolderPath = path.join(homeDir, ".roo", `rules-${slug}`)
573+
}
574+
575+
// Check if the rules folder exists and delete it
576+
const rulesFolderExists = await fileExistsAtPath(rulesFolderPath)
577+
if (rulesFolderExists) {
578+
try {
579+
await fs.rm(rulesFolderPath, { recursive: true, force: true })
580+
logger.info(`Deleted rules folder for mode ${slug}: ${rulesFolderPath}`)
581+
} catch (error) {
582+
logger.error(`Failed to delete rules folder for mode ${slug}: ${error}`)
583+
// Notify the user about the failure
584+
const messageKey = fromMarketplace
585+
? "common:marketplace.mode.rulesCleanupFailed"
586+
: "common:customModes.errors.rulesCleanupFailed"
587+
vscode.window.showWarningMessage(t(messageKey, { rulesFolderPath }))
588+
// Continue even if folder deletion fails
589+
}
590+
}
591+
} catch (error) {
592+
logger.error(`Error deleting rules folder for mode ${slug}`, {
593+
error: error instanceof Error ? error.message : String(error),
594+
})
595+
}
596+
}
597+
541598
public async resetCustomModes(): Promise<void> {
542599
try {
543600
const filePath = await this.getCustomModesFilePath()

src/core/webview/ClineProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ export class ClineProvider
158158
this.log(`Failed to initialize MCP Hub: ${error}`)
159159
})
160160

161-
this.marketplaceManager = new MarketplaceManager(this.context)
161+
this.marketplaceManager = new MarketplaceManager(this.context, this.customModesManager)
162162
}
163163

164164
// Adds a new Cline instance to clineStack, marking the start of a new task.

src/core/webview/webviewMessageHandler.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2229,8 +2229,45 @@ export const webviewMessageHandler = async (
22292229
try {
22302230
await marketplaceManager.removeInstalledMarketplaceItem(message.mpItem, message.mpInstallOptions)
22312231
await provider.postStateToWebview()
2232+
2233+
// Send success message to webview
2234+
provider.postMessageToWebview({
2235+
type: "marketplaceRemoveResult",
2236+
success: true,
2237+
slug: message.mpItem.id,
2238+
})
22322239
} catch (error) {
22332240
console.error(`Error removing marketplace item: ${error}`)
2241+
2242+
// Show error message to user
2243+
vscode.window.showErrorMessage(
2244+
`Failed to remove marketplace item: ${error instanceof Error ? error.message : String(error)}`,
2245+
)
2246+
2247+
// Send error message to webview
2248+
provider.postMessageToWebview({
2249+
type: "marketplaceRemoveResult",
2250+
success: false,
2251+
error: error instanceof Error ? error.message : String(error),
2252+
slug: message.mpItem.id,
2253+
})
2254+
}
2255+
} else {
2256+
// MarketplaceManager not available or missing required parameters
2257+
const errorMessage = !marketplaceManager
2258+
? "Marketplace manager is not available"
2259+
: "Missing required parameters for marketplace item removal"
2260+
console.error(errorMessage)
2261+
2262+
vscode.window.showErrorMessage(errorMessage)
2263+
2264+
if (message.mpItem?.id) {
2265+
provider.postMessageToWebview({
2266+
type: "marketplaceRemoveResult",
2267+
success: false,
2268+
error: errorMessage,
2269+
slug: message.mpItem.id,
2270+
})
22342271
}
22352272
}
22362273
break

src/i18n/locales/ca/common.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/de/common.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/en/common.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,19 @@
136136
"deleteFailed": "Failed to delete custom mode: {{error}}",
137137
"resetFailed": "Failed to reset custom modes: {{error}}",
138138
"modeNotFound": "Write error: Mode not found",
139-
"noWorkspaceForProject": "No workspace folder found for project-specific mode"
139+
"noWorkspaceForProject": "No workspace folder found for project-specific mode",
140+
"rulesCleanupFailed": "Mode deleted successfully, but failed to delete rules folder at {{rulesFolderPath}}. You may need to delete it manually."
140141
},
141142
"scope": {
142143
"project": "project",
143144
"global": "global"
144145
}
145146
},
147+
"marketplace": {
148+
"mode": {
149+
"rulesCleanupFailed": "Mode removed successfully, but failed to delete rules folder at {{rulesFolderPath}}. You may need to delete it manually."
150+
}
151+
},
146152
"mdm": {
147153
"errors": {
148154
"cloud_auth_required": "Your organization requires Roo Code Cloud authentication. Please sign in to continue.",

src/i18n/locales/es/common.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/fr/common.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/hi/common.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/id/common.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)