Skip to content

Commit a688883

Browse files
committed
Merge main and update marketplace
2 parents 1d63fb6 + 7e8ff7e commit a688883

File tree

135 files changed

+8404
-104
lines changed

Some content is hidden

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

135 files changed

+8404
-104
lines changed

PRIVACY.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Roo Code Privacy Policy
22

3-
**Last Updated: March 7th, 2025**
3+
**Last Updated: June 10th, 2025**
44

55
Roo Code respects your privacy and is committed to transparency about how we handle your data. Below is a simple breakdown of where key pieces of data go—and, importantly, where they don’t.
66

@@ -11,6 +11,7 @@ Roo Code respects your privacy and is committed to transparency about how we han
1111
- **Prompts & AI Requests**: When you use AI-powered features, your prompts and relevant project context are sent to your chosen AI model provider (e.g., OpenAI, Anthropic, OpenRouter) to generate responses. We do not store or process this data. These AI providers have their own privacy policies and may store data per their terms of service.
1212
- **API Keys & Credentials**: If you enter an API key (e.g., to connect an AI model), it is stored locally on your device and never sent to us or any third party, except the provider you have chosen.
1313
- **Telemetry (Usage Data)**: We only collect feature usage and error data if you explicitly opt-in. This telemetry is powered by PostHog and helps us understand feature usage to improve Roo Code. This includes your VS Code machine ID and feature usage patterns and exception reports. We do **not** collect personally identifiable information, your code, or AI prompts.
14+
- **Marketplace Requests**: When you browse or search the Marketplace for Model Configuration Profiles (MCPs) or Custom Modes, Roo Code makes a secure API call to Roo Code’s backend servers to retrieve listing information. These requests send only the query parameters (e.g., extension version, search term) necessary to fulfill the request and do not include your code, prompts, or personally identifiable information.
1415

1516
### **How We Use Your Data (If Collected)**
1617

packages/cloud/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from "./CloudService"
2+
export * from "./Config"

packages/evals/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ To stop an evals run early you can simply stop the "controller" container using
6868

6969
<img width="1302" alt="Screenshot 2025-06-06 at 9 00 41 AM" src="https://github.com/user-attachments/assets/a9d4725b-730c-441a-ba24-ac99f9599ced" />
7070

71-
7271
## Advanced Usage / Debugging
7372

7473
The evals system runs VS Code headlessly in Docker containers for consistent, reproducible environments. While this design ensures reliability, it can make debugging more challenging. For debugging purposes, you can run the system locally on macOS, though this approach is less reliable due to hardware and environment variability.

packages/types/src/experiment.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import type { Keys, Equals, AssertEqual } from "./type-fu.js"
66
* ExperimentId
77
*/
88

9-
export const experimentIds = ["powerSteering", "concurrentFileReads", "disableCompletionCommand"] as const
9+
export const experimentIds = [
10+
"powerSteering",
11+
"marketplace",
12+
"concurrentFileReads",
13+
"disableCompletionCommand",
14+
] as const
1015

1116
export const experimentIdsSchema = z.enum(experimentIds)
1217

@@ -18,6 +23,7 @@ export type ExperimentId = z.infer<typeof experimentIdsSchema>
1823

1924
export const experimentsSchema = z.object({
2025
powerSteering: z.boolean(),
26+
marketplace: z.boolean(),
2127
concurrentFileReads: z.boolean(),
2228
disableCompletionCommand: z.boolean(),
2329
})

packages/types/src/vscode.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export const commandIds = [
3333
"promptsButtonClicked",
3434
"mcpButtonClicked",
3535
"historyButtonClicked",
36+
"marketplaceButtonClicked",
3637
"popoutButtonClicked",
3738
"accountButtonClicked",
3839
"settingsButtonClicked",

src/activate/registerCommands.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
146146

147147
visibleProvider.postMessageToWebview({ type: "action", action: "historyButtonClicked" })
148148
},
149+
marketplaceButtonClicked: () => {
150+
const visibleProvider = getVisibleProviderOrLog(outputChannel)
151+
if (!visibleProvider) return
152+
visibleProvider.postMessageToWebview({ type: "action", action: "marketplaceButtonClicked" })
153+
},
149154
showHumanRelayDialog: (params: { requestId: string; promptText: string }) => {
150155
const panel = getPanel()
151156

src/core/config/CustomModesManager.ts

Lines changed: 75 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { fileExistsAtPath } from "../../utils/fs"
1010
import { arePathsEqual, getWorkspacePath } from "../../utils/path"
1111
import { logger } from "../../utils/logging"
1212
import { GlobalFileNames } from "../../shared/globalFileNames"
13+
import { ensureSettingsDirectoryExists } from "../../utils/globalContext"
1314

1415
const ROOMODES_FILENAME = ".roomodes"
1516

@@ -27,7 +28,12 @@ export class CustomModesManager {
2728
private readonly onUpdate: () => Promise<void>,
2829
) {
2930
// TODO: We really shouldn't have async methods in the constructor.
30-
this.watchCustomModesFiles()
31+
// Defer the file watching setup to avoid issues in test environments
32+
process.nextTick(() => {
33+
this.watchCustomModesFiles().catch((error) => {
34+
console.error("[CustomModesManager] Failed to setup file watchers:", error)
35+
})
36+
})
3137
}
3238

3339
private async queueWrite(operation: () => Promise<void>): Promise<void> {
@@ -117,7 +123,7 @@ export class CustomModesManager {
117123
}
118124

119125
public async getCustomModesFilePath(): Promise<string> {
120-
const settingsDir = await this.ensureSettingsDirectoryExists()
126+
const settingsDir = await ensureSettingsDirectoryExists(this.context)
121127
const filePath = path.join(settingsDir, GlobalFileNames.customModes)
122128
const fileExists = await fileExistsAtPath(filePath)
123129

@@ -132,61 +138,84 @@ export class CustomModesManager {
132138
const settingsPath = await this.getCustomModesFilePath()
133139

134140
// Watch settings file
135-
this.disposables.push(
136-
vscode.workspace.onDidSaveTextDocument(async (document) => {
137-
if (arePathsEqual(document.uri.fsPath, settingsPath)) {
138-
const content = await fs.readFile(settingsPath, "utf-8")
139-
140-
const errorMessage =
141-
"Invalid custom modes format. Please ensure your settings follow the correct YAML format."
141+
const settingsWatcher = vscode.workspace.createFileSystemWatcher(settingsPath)
142142

143-
let config: any
143+
const handleSettingsChange = async () => {
144+
try {
145+
const content = await fs.readFile(settingsPath, "utf-8")
144146

145-
try {
146-
config = yaml.parse(content)
147-
} catch (error) {
148-
console.error(error)
149-
vscode.window.showErrorMessage(errorMessage)
150-
return
151-
}
147+
const errorMessage =
148+
"Invalid custom modes format. Please ensure your settings follow the correct YAML format."
152149

153-
const result = customModesSettingsSchema.safeParse(config)
150+
let config: any
154151

155-
if (!result.success) {
156-
vscode.window.showErrorMessage(errorMessage)
157-
return
158-
}
152+
try {
153+
config = yaml.parse(content)
154+
} catch (error) {
155+
console.error(error)
156+
vscode.window.showErrorMessage(errorMessage)
157+
return
158+
}
159159

160-
// Get modes from .roomodes if it exists (takes precedence)
161-
const roomodesPath = await this.getWorkspaceRoomodes()
162-
const roomodesModes = roomodesPath ? await this.loadModesFromFile(roomodesPath) : []
160+
const result = customModesSettingsSchema.safeParse(config)
163161

164-
// Merge modes from both sources (.roomodes takes precedence)
165-
const mergedModes = await this.mergeCustomModes(roomodesModes, result.data.customModes)
166-
await this.context.globalState.update("customModes", mergedModes)
167-
this.clearCache()
168-
await this.onUpdate()
162+
if (!result.success) {
163+
vscode.window.showErrorMessage(errorMessage)
164+
return
169165
}
170-
}),
171-
)
166+
167+
// Get modes from .roomodes if it exists (takes precedence)
168+
const roomodesPath = await this.getWorkspaceRoomodes()
169+
const roomodesModes = roomodesPath ? await this.loadModesFromFile(roomodesPath) : []
170+
171+
// Merge modes from both sources (.roomodes takes precedence)
172+
const mergedModes = await this.mergeCustomModes(roomodesModes, result.data.customModes)
173+
await this.context.globalState.update("customModes", mergedModes)
174+
this.clearCache()
175+
await this.onUpdate()
176+
} catch (error) {
177+
console.error(`[CustomModesManager] Error handling settings file change:`, error)
178+
}
179+
}
180+
181+
this.disposables.push(settingsWatcher.onDidChange(handleSettingsChange))
182+
this.disposables.push(settingsWatcher.onDidCreate(handleSettingsChange))
183+
this.disposables.push(settingsWatcher)
172184

173185
// Watch .roomodes file if it exists
174186
const roomodesPath = await this.getWorkspaceRoomodes()
175187

176188
if (roomodesPath) {
177-
this.disposables.push(
178-
vscode.workspace.onDidSaveTextDocument(async (document) => {
179-
if (arePathsEqual(document.uri.fsPath, roomodesPath)) {
180-
const settingsModes = await this.loadModesFromFile(settingsPath)
181-
const roomodesModes = await this.loadModesFromFile(roomodesPath)
182-
// .roomodes takes precedence
183-
const mergedModes = await this.mergeCustomModes(roomodesModes, settingsModes)
184-
await this.context.globalState.update("customModes", mergedModes)
185-
this.clearCache()
186-
await this.onUpdate()
187-
}
188-
}),
189-
)
189+
const roomodesWatcher = vscode.workspace.createFileSystemWatcher(roomodesPath)
190+
191+
const handleRoomodesChange = async () => {
192+
try {
193+
const settingsModes = await this.loadModesFromFile(settingsPath)
194+
const roomodesModes = await this.loadModesFromFile(roomodesPath)
195+
// .roomodes takes precedence
196+
const mergedModes = await this.mergeCustomModes(roomodesModes, settingsModes)
197+
await this.context.globalState.update("customModes", mergedModes)
198+
this.clearCache()
199+
await this.onUpdate()
200+
} catch (error) {
201+
console.error(`[CustomModesManager] Error handling .roomodes file change:`, error)
202+
}
203+
}
204+
205+
roomodesWatcher.onDidChange(handleRoomodesChange)
206+
roomodesWatcher.onDidCreate(handleRoomodesChange)
207+
roomodesWatcher.onDidDelete(async () => {
208+
// When .roomodes is deleted, refresh with only settings modes
209+
try {
210+
const settingsModes = await this.loadModesFromFile(settingsPath)
211+
await this.context.globalState.update("customModes", settingsModes)
212+
this.clearCache()
213+
await this.onUpdate()
214+
} catch (error) {
215+
console.error(`[CustomModesManager] Error handling .roomodes file deletion:`, error)
216+
}
217+
})
218+
this.disposables.push(roomodesWatcher)
190219
}
191220
}
192221

@@ -309,7 +338,7 @@ export class CustomModesManager {
309338
await fs.writeFile(filePath, yaml.stringify(settings), "utf-8")
310339
}
311340

312-
private async refreshMergedState(): Promise<void> {
341+
public async refreshMergedState(): Promise<void> {
313342
const settingsPath = await this.getCustomModesFilePath()
314343
const roomodesPath = await this.getWorkspaceRoomodes()
315344

@@ -362,12 +391,6 @@ export class CustomModesManager {
362391
}
363392
}
364393

365-
private async ensureSettingsDirectoryExists(): Promise<string> {
366-
const settingsDir = path.join(this.context.globalStorageUri.fsPath, "settings")
367-
await fs.mkdir(settingsDir, { recursive: true })
368-
return settingsDir
369-
}
370-
371394
public async resetCustomModes(): Promise<void> {
372395
try {
373396
const filePath = await this.getCustomModesFilePath()

0 commit comments

Comments
 (0)