Matt Rubens 6 месяцев назад
Родитель
Сommit
7b5a1d987d

+ 1 - 2
packages/types/src/experiment.ts

@@ -6,7 +6,7 @@ import type { Keys, Equals, AssertEqual } from "./type-fu.js"
  * ExperimentId
  */
 
-export const experimentIds = ["powerSteering", "disableCompletionCommand", "marketplace", "multiFileApplyDiff"] as const
+export const experimentIds = ["powerSteering", "disableCompletionCommand", "multiFileApplyDiff"] as const
 
 export const experimentIdsSchema = z.enum(experimentIds)
 
@@ -19,7 +19,6 @@ export type ExperimentId = z.infer<typeof experimentIdsSchema>
 export const experimentsSchema = z.object({
 	powerSteering: z.boolean().optional(),
 	disableCompletionCommand: z.boolean().optional(),
-	marketplace: z.boolean().optional(),
 	multiFileApplyDiff: z.boolean().optional(),
 })
 

+ 3 - 25
src/core/webview/ClineProvider.ts

@@ -502,9 +502,6 @@ export class ClineProvider
 		// If the extension is starting a new session, clear previous task state.
 		await this.removeClineFromStack()
 
-		// Set initial VSCode context for experiments
-		await this.updateVSCodeContext()
-
 		this.log("Webview view resolved")
 	}
 
@@ -1245,29 +1242,12 @@ export class ClineProvider
 		const state = await this.getStateToPostToWebview()
 		this.postMessageToWebview({ type: "state", state })
 
-		// Update VSCode context for experiments
-		await this.updateVSCodeContext()
-
 		// Check MDM compliance and send user to account tab if not compliant
 		if (!this.checkMdmCompliance()) {
 			await this.postMessageToWebview({ type: "action", action: "accountButtonClicked" })
 		}
 	}
 
-	/**
-	 * Updates VSCode context variables for experiments so they can be used in when clauses
-	 */
-	private async updateVSCodeContext() {
-		const { experiments } = await this.getState()
-
-		// Set context for marketplace experiment
-		await vscode.commands.executeCommand(
-			"setContext",
-			`${Package.name}.marketplaceEnabled`,
-			experiments.marketplace ?? false,
-		)
-	}
-
 	/**
 	 * Checks if there is a file-based system prompt override for the given mode
 	 */
@@ -1356,14 +1336,12 @@ export class ClineProvider
 		const allowedCommands = vscode.workspace.getConfiguration(Package.name).get<string[]>("allowedCommands") || []
 		const cwd = this.cwd
 
-		// Only fetch marketplace data if the feature is enabled
+		// Fetch marketplace data
 		let marketplaceItems: any[] = []
 		let marketplaceInstalledMetadata: any = { project: {}, global: {} }
 
-		if (experiments.marketplace) {
-			marketplaceItems = (await this.marketplaceManager.getCurrentItems()) || []
-			marketplaceInstalledMetadata = await this.marketplaceManager.getInstallationMetadata()
-		}
+		marketplaceItems = (await this.marketplaceManager.getCurrentItems()) || []
+		marketplaceInstalledMetadata = await this.marketplaceManager.getInstallationMetadata()
 
 		// Check if there's a system prompt override for the current mode
 		const currentMode = mode ?? defaultModeSlug

+ 0 - 28
src/core/webview/webviewMessageHandler.ts

@@ -1465,13 +1465,6 @@ export const webviewMessageHandler = async (
 			break
 		}
 		case "filterMarketplaceItems": {
-			// Check if marketplace is enabled before making API calls
-			const { experiments } = await provider.getState()
-			if (!experiments.marketplace) {
-				console.log("Marketplace: Feature disabled, skipping API call")
-				break
-			}
-
 			if (marketplaceManager && message.filters) {
 				try {
 					await marketplaceManager.updateWithFilteredItems({
@@ -1489,13 +1482,6 @@ export const webviewMessageHandler = async (
 		}
 
 		case "installMarketplaceItem": {
-			// Check if marketplace is enabled before installing
-			const { experiments } = await provider.getState()
-			if (!experiments.marketplace) {
-				console.log("Marketplace: Feature disabled, skipping installation")
-				break
-			}
-
 			if (marketplaceManager && message.mpItem && message.mpInstallOptions) {
 				try {
 					const configFilePath = await marketplaceManager.installMarketplaceItem(
@@ -1525,13 +1511,6 @@ export const webviewMessageHandler = async (
 		}
 
 		case "removeInstalledMarketplaceItem": {
-			// Check if marketplace is enabled before removing
-			const { experiments } = await provider.getState()
-			if (!experiments.marketplace) {
-				console.log("Marketplace: Feature disabled, skipping removal")
-				break
-			}
-
 			if (marketplaceManager && message.mpItem && message.mpInstallOptions) {
 				try {
 					await marketplaceManager.removeInstalledMarketplaceItem(message.mpItem, message.mpInstallOptions)
@@ -1544,13 +1523,6 @@ export const webviewMessageHandler = async (
 		}
 
 		case "installMarketplaceItemWithParameters": {
-			// Check if marketplace is enabled before installing with parameters
-			const { experiments } = await provider.getState()
-			if (!experiments.marketplace) {
-				console.log("Marketplace: Feature disabled, skipping installation with parameters")
-				break
-			}
-
 			if (marketplaceManager && message.payload && "item" in message.payload && "parameters" in message.payload) {
 				try {
 					const configFilePath = await marketplaceManager.installMarketplaceItem(message.payload.item, {

+ 2 - 2
src/package.json

@@ -232,7 +232,7 @@
 				{
 					"command": "roo-cline.marketplaceButtonClicked",
 					"group": "navigation@4",
-					"when": "view == roo-cline.SidebarProvider && roo-cline.marketplaceEnabled"
+					"when": "view == roo-cline.SidebarProvider"
 				},
 				{
 					"command": "roo-cline.historyButtonClicked",
@@ -274,7 +274,7 @@
 				{
 					"command": "roo-cline.marketplaceButtonClicked",
 					"group": "navigation@4",
-					"when": "activeWebviewPanelId == roo-cline.TabPanelProvider && roo-cline.marketplaceEnabled"
+					"when": "activeWebviewPanelId == roo-cline.TabPanelProvider"
 				},
 				{
 					"command": "roo-cline.historyButtonClicked",

+ 12 - 29
src/services/marketplace/__tests__/marketplace-setting-check.spec.ts

@@ -6,21 +6,22 @@ import { webviewMessageHandler } from "../../../core/webview/webviewMessageHandl
 const mockProvider = {
 	getState: vi.fn(),
 	postStateToWebview: vi.fn(),
+	postMessageToWebview: vi.fn(),
 } as any
 
 const mockMarketplaceManager = {
 	updateWithFilteredItems: vi.fn(),
 } as any
 
-describe("Marketplace Setting Check", () => {
+describe("Marketplace General Availability", () => {
 	beforeEach(() => {
 		vi.clearAllMocks()
 	})
 
-	it("should skip API calls when marketplace is disabled", async () => {
-		// Mock experiments with marketplace disabled
+	it("should allow marketplace API calls (marketplace is generally available)", async () => {
+		// Mock state without marketplace experiment (since it's now generally available)
 		mockProvider.getState.mockResolvedValue({
-			experiments: { marketplace: false },
+			experiments: {},
 		})
 
 		const message = {
@@ -30,25 +31,7 @@ describe("Marketplace Setting Check", () => {
 
 		await webviewMessageHandler(mockProvider, message, mockMarketplaceManager)
 
-		// Should not call marketplace manager methods
-		expect(mockMarketplaceManager.updateWithFilteredItems).not.toHaveBeenCalled()
-		expect(mockProvider.postStateToWebview).not.toHaveBeenCalled()
-	})
-
-	it("should allow API calls when marketplace is enabled", async () => {
-		// Mock experiments with marketplace enabled
-		mockProvider.getState.mockResolvedValue({
-			experiments: { marketplace: true },
-		})
-
-		const message = {
-			type: "filterMarketplaceItems" as const,
-			filters: { type: "mcp", search: "", tags: [] },
-		}
-
-		await webviewMessageHandler(mockProvider, message, mockMarketplaceManager)
-
-		// Should call marketplace manager methods
+		// Should call marketplace manager methods since marketplace is generally available
 		expect(mockMarketplaceManager.updateWithFilteredItems).toHaveBeenCalledWith({
 			type: "mcp",
 			search: "",
@@ -57,13 +40,13 @@ describe("Marketplace Setting Check", () => {
 		expect(mockProvider.postStateToWebview).toHaveBeenCalled()
 	})
 
-	it("should skip installation when marketplace is disabled", async () => {
-		// Mock experiments with marketplace disabled
+	it("should allow marketplace installation (marketplace is generally available)", async () => {
+		// Mock state without marketplace experiment (since it's now generally available)
 		mockProvider.getState.mockResolvedValue({
-			experiments: { marketplace: false },
+			experiments: {},
 		})
 
-		const mockInstallMarketplaceItem = vi.fn()
+		const mockInstallMarketplaceItem = vi.fn().mockResolvedValue(undefined)
 		const mockMarketplaceManagerWithInstall = {
 			installMarketplaceItem: mockInstallMarketplaceItem,
 		}
@@ -83,7 +66,7 @@ describe("Marketplace Setting Check", () => {
 
 		await webviewMessageHandler(mockProvider, message, mockMarketplaceManagerWithInstall as any)
 
-		// Should not call install method
-		expect(mockInstallMarketplaceItem).not.toHaveBeenCalled()
+		// Should call install method since marketplace is generally available
+		expect(mockInstallMarketplaceItem).toHaveBeenCalledWith(message.mpItem, message.mpInstallOptions)
 	})
 })

+ 0 - 41
src/shared/__tests__/experiments.spec.ts

@@ -27,7 +27,6 @@ describe("experiments", () => {
 		it("returns false when POWER_STEERING experiment is not enabled", () => {
 			const experiments: Record<ExperimentId, boolean> = {
 				powerSteering: false,
-				marketplace: false,
 				disableCompletionCommand: false,
 				multiFileApplyDiff: false,
 			}
@@ -37,7 +36,6 @@ describe("experiments", () => {
 		it("returns true when experiment POWER_STEERING is enabled", () => {
 			const experiments: Record<ExperimentId, boolean> = {
 				powerSteering: true,
-				marketplace: false,
 				disableCompletionCommand: false,
 				multiFileApplyDiff: false,
 			}
@@ -47,49 +45,10 @@ describe("experiments", () => {
 		it("returns false when experiment is not present", () => {
 			const experiments: Record<ExperimentId, boolean> = {
 				powerSteering: false,
-				marketplace: false,
 				disableCompletionCommand: false,
 				multiFileApplyDiff: false,
 			}
 			expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.POWER_STEERING)).toBe(false)
 		})
 	})
-	describe("MARKETPLACE", () => {
-		it("is configured correctly", () => {
-			expect(EXPERIMENT_IDS.MARKETPLACE).toBe("marketplace")
-			expect(experimentConfigsMap.MARKETPLACE).toMatchObject({
-				enabled: false,
-			})
-		})
-	})
-
-	describe("isEnabled for MARKETPLACE", () => {
-		it("returns false when MARKETPLACE experiment is not enabled", () => {
-			const experiments: Record<ExperimentId, boolean> = {
-				powerSteering: false,
-				marketplace: false,
-				disableCompletionCommand: false,
-				multiFileApplyDiff: false,
-			}
-			expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.MARKETPLACE)).toBe(false)
-		})
-
-		it("returns true when MARKETPLACE experiment is enabled", () => {
-			const experiments: Record<ExperimentId, boolean> = {
-				powerSteering: false,
-				marketplace: true,
-				disableCompletionCommand: false,
-				multiFileApplyDiff: false,
-			}
-			expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.MARKETPLACE)).toBe(true)
-		})
-
-		it("returns false when MARKETPLACE experiment is not present", () => {
-			const experiments: Record<ExperimentId, boolean> = {
-				powerSteering: false,
-				// marketplace missing
-			} as any
-			expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.MARKETPLACE)).toBe(false)
-		})
-	})
 })

+ 0 - 2
src/shared/experiments.ts

@@ -1,7 +1,6 @@
 import type { AssertEqual, Equals, Keys, Values, ExperimentId, Experiments } from "@roo-code/types"
 
 export const EXPERIMENT_IDS = {
-	MARKETPLACE: "marketplace",
 	MULTI_FILE_APPLY_DIFF: "multiFileApplyDiff",
 	DISABLE_COMPLETION_COMMAND: "disableCompletionCommand",
 	POWER_STEERING: "powerSteering",
@@ -16,7 +15,6 @@ interface ExperimentConfig {
 }
 
 export const experimentConfigsMap: Record<ExperimentKey, ExperimentConfig> = {
-	MARKETPLACE: { enabled: false },
 	MULTI_FILE_APPLY_DIFF: { enabled: false },
 	DISABLE_COMPLETION_COMMAND: { enabled: false },
 	POWER_STEERING: { enabled: false },

+ 3 - 12
webview-ui/src/App.tsx

@@ -40,7 +40,6 @@ const App = () => {
 		telemetrySetting,
 		telemetryKey,
 		machineId,
-		experiments,
 		cloudUserInfo,
 		cloudIsAuthenticated,
 		mdmCompliant,
@@ -93,10 +92,6 @@ const App = () => {
 				// Handle switchTab action with tab parameter
 				if (message.action === "switchTab" && message.tab) {
 					const targetTab = message.tab as Tab
-					// Don't switch to marketplace tab if the experiment is disabled
-					if (targetTab === "marketplace" && !experiments.marketplace) {
-						return
-					}
 					switchTab(targetTab)
 					setCurrentSection(undefined)
 				} else {
@@ -105,10 +100,6 @@ const App = () => {
 					const section = message.values?.section as string | undefined
 
 					if (newTab) {
-						// Don't switch to marketplace tab if the experiment is disabled
-						if (newTab === "marketplace" && !experiments.marketplace) {
-							return
-						}
 						switchTab(newTab)
 						setCurrentSection(section)
 					}
@@ -124,7 +115,7 @@ const App = () => {
 				chatViewRef.current?.acceptInput()
 			}
 		},
-		[switchTab, experiments],
+		[switchTab],
 	)
 
 	useEvent("message", onMessage)
@@ -147,10 +138,10 @@ const App = () => {
 
 	// Track marketplace tab views
 	useEffect(() => {
-		if (tab === "marketplace" && experiments.marketplace) {
+		if (tab === "marketplace") {
 			telemetryClient.capture(TelemetryEventName.MARKETPLACE_TAB_VIEWED)
 		}
-	}, [tab, experiments.marketplace])
+	}, [tab])
 
 	if (!didHydrateState) {
 		return null

+ 22 - 61
webview-ui/src/__tests__/App.test.tsx

@@ -104,7 +104,7 @@ describe("App", () => {
 			didHydrateState: true,
 			showWelcome: false,
 			shouldShowAnnouncement: false,
-			experiments: { marketplace: false },
+			experiments: {},
 			language: "en",
 		})
 	})
@@ -224,74 +224,35 @@ describe("App", () => {
 		expect(screen.queryByTestId(`${view}-view`)).not.toBeInTheDocument()
 	})
 
-	describe("marketplace experiment", () => {
-		it("does not switch to marketplace tab when experiment is disabled", async () => {
-			mockUseExtensionState.mockReturnValue({
-				didHydrateState: true,
-				showWelcome: false,
-				shouldShowAnnouncement: false,
-				experiments: { marketplace: false },
-				language: "en",
-			})
-
-			render(<AppWithProviders />)
-
-			act(() => {
-				triggerMessage("marketplaceButtonClicked")
-			})
-
-			// Should remain on chat view
-			const chatView = screen.getByTestId("chat-view")
-			expect(chatView.getAttribute("data-hidden")).toBe("false")
-			expect(screen.queryByTestId("marketplace-view")).not.toBeInTheDocument()
-		})
-
-		it("switches to marketplace tab when experiment is enabled", async () => {
-			mockUseExtensionState.mockReturnValue({
-				didHydrateState: true,
-				showWelcome: false,
-				shouldShowAnnouncement: false,
-				experiments: { marketplace: true },
-				language: "en",
-			})
-
-			render(<AppWithProviders />)
-
-			act(() => {
-				triggerMessage("marketplaceButtonClicked")
-			})
-
-			const marketplaceView = await screen.findByTestId("marketplace-view")
-			expect(marketplaceView).toBeInTheDocument()
+	it("switches to marketplace view when receiving marketplaceButtonClicked action", async () => {
+		render(<AppWithProviders />)
 
-			const chatView = screen.getByTestId("chat-view")
-			expect(chatView.getAttribute("data-hidden")).toBe("true")
+		act(() => {
+			triggerMessage("marketplaceButtonClicked")
 		})
 
-		it("returns to chat view when clicking done in marketplace view", async () => {
-			mockUseExtensionState.mockReturnValue({
-				didHydrateState: true,
-				showWelcome: false,
-				shouldShowAnnouncement: false,
-				experiments: { marketplace: true },
-				language: "en",
-			})
+		const marketplaceView = await screen.findByTestId("marketplace-view")
+		expect(marketplaceView).toBeInTheDocument()
 
-			render(<AppWithProviders />)
+		const chatView = screen.getByTestId("chat-view")
+		expect(chatView.getAttribute("data-hidden")).toBe("true")
+	})
 
-			act(() => {
-				triggerMessage("marketplaceButtonClicked")
-			})
+	it("returns to chat view when clicking done in marketplace view", async () => {
+		render(<AppWithProviders />)
 
-			const marketplaceView = await screen.findByTestId("marketplace-view")
+		act(() => {
+			triggerMessage("marketplaceButtonClicked")
+		})
 
-			act(() => {
-				marketplaceView.click()
-			})
+		const marketplaceView = await screen.findByTestId("marketplace-view")
 
-			const chatView = screen.getByTestId("chat-view")
-			expect(chatView.getAttribute("data-hidden")).toBe("false")
-			expect(screen.queryByTestId("marketplace-view")).not.toBeInTheDocument()
+		act(() => {
+			marketplaceView.click()
 		})
+
+		const chatView = screen.getByTestId("chat-view")
+		expect(chatView.getAttribute("data-hidden")).toBe("false")
+		expect(screen.queryByTestId("marketplace-view")).not.toBeInTheDocument()
 	})
 })

+ 1 - 1
webview-ui/src/components/settings/ExperimentalSettings.tsx

@@ -52,7 +52,7 @@ export const ExperimentalSettings = ({
 
 			<Section>
 				{Object.entries(experimentConfigsMap)
-					.filter((config) => config[0] !== "DIFF_STRATEGY" && config[0] !== "MULTI_SEARCH_AND_REPLACE")
+					.filter(([key]) => key in EXPERIMENT_IDS)
 					.map((config) => {
 						if (config[0] === "MULTI_FILE_APPLY_DIFF") {
 							return (