diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts
index f1c4b81c48..3afc1f5f63 100644
--- a/packages/types/src/global-settings.ts
+++ b/packages/types/src/global-settings.ts
@@ -41,6 +41,7 @@ export const globalSettingsSchema = z.object({
lastShownAnnouncementId: z.string().optional(),
customInstructions: z.string().optional(),
taskHistory: z.array(historyItemSchema).optional(),
+ showCloudPromotion: z.boolean().optional(),
// Image generation settings (experimental) - flattened for simplicity
openRouterImageApiKey: z.string().optional(),
@@ -321,6 +322,8 @@ export const EVALS_SETTINGS: RooCodeSettings = {
mode: "code", // "architect",
customModes: [],
+
+ showCloudPromotion: true, // Default to true to maintain current behavior
}
export const EVALS_TIMEOUT = 5 * 60 * 1_000
diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts
index 1565bb8c52..648d4fb819 100644
--- a/src/shared/ExtensionMessage.ts
+++ b/src/shared/ExtensionMessage.ts
@@ -209,6 +209,7 @@ export type ExtensionState = Pick<
// | "lastShownAnnouncementId"
| "customInstructions"
// | "taskHistory" // Optional in GlobalSettings, required here.
+ | "showCloudPromotion"
| "autoApprovalEnabled"
| "alwaysAllowReadOnly"
| "alwaysAllowReadOnlyOutsideWorkspace"
diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx
index 3e13905bc9..e9ba034354 100644
--- a/webview-ui/src/components/chat/ChatView.tsx
+++ b/webview-ui/src/components/chat/ChatView.tsx
@@ -120,6 +120,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction}
- {cloudIsAuthenticated || taskHistory.length < 4 ? : }
+ {cloudIsAuthenticated || taskHistory.length < 4 || !showCloudPromotion ? (
+
+ ) : (
+
+ )}
{/* Show the task history preview if expanded and tasks exist */}
{taskHistory.length > 0 && isExpanded && }
diff --git a/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx
index 09d46083d4..2aae924bf3 100644
--- a/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx
+++ b/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx
@@ -1428,6 +1428,44 @@ describe("ChatView - RooCloudCTA Display Tests", () => {
expect(queryByTestId("roo-cloud-cta")).not.toBeInTheDocument()
expect(getByTestId("roo-tips")).toBeInTheDocument()
})
+
+ it("does not show RooCloudCTA when showCloudPromotion is false", () => {
+ const { queryByTestId, getByTestId } = renderChatView()
+
+ // Set showCloudPromotion to false
+ act(() => {
+ mockPostMessage({
+ showCloudPromotion: false,
+ cloudIsAuthenticated: false,
+ taskHistory: Array(5).fill({ id: "task", ts: Date.now() }),
+ clineMessages: [], // No active task
+ })
+ })
+
+ // Should not show RooCloudCTA when showCloudPromotion is false
+ expect(queryByTestId("roo-cloud-cta")).not.toBeInTheDocument()
+ // Should show RooTips instead
+ expect(getByTestId("roo-tips")).toBeInTheDocument()
+ })
+
+ it("shows RooCloudCTA when showCloudPromotion is true and conditions are met", async () => {
+ const { getByTestId } = renderChatView()
+
+ // Set showCloudPromotion to true with conditions met
+ act(() => {
+ mockPostMessage({
+ showCloudPromotion: true,
+ cloudIsAuthenticated: false,
+ taskHistory: Array(5).fill({ id: "task", ts: Date.now() }),
+ clineMessages: [], // No active task
+ })
+ })
+
+ // Should show RooCloudCTA when showCloudPromotion is true and conditions are met
+ await waitFor(() => {
+ expect(getByTestId("roo-cloud-cta")).toBeInTheDocument()
+ })
+ })
})
describe("ChatView - Message Queueing Tests", () => {
diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx
index 2f4af84f58..5f4dfca51e 100644
--- a/webview-ui/src/context/ExtensionStateContext.tsx
+++ b/webview-ui/src/context/ExtensionStateContext.tsx
@@ -44,6 +44,8 @@ export interface ExtensionStateContextType extends ExtensionState {
mdmCompliant?: boolean
hasOpenedModeSelector: boolean // New property to track if user has opened mode selector
setHasOpenedModeSelector: (value: boolean) => void // Setter for the new property
+ showCloudPromotion: boolean // New property for cloud promotion visibility
+ setShowCloudPromotion: (value: boolean) => void // Setter for cloud promotion
alwaysAllowFollowupQuestions: boolean // New property for follow-up questions auto-approve
setAlwaysAllowFollowupQuestions: (value: boolean) => void // Setter for the new property
followupAutoApproveTimeoutMs: number | undefined // Timeout in ms for auto-approving follow-up questions
@@ -255,6 +257,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
maxDiagnosticMessages: 50,
openRouterImageApiKey: "",
openRouterImageGenerationSelectedModel: "",
+ showCloudPromotion: true, // Default to true to maintain current behavior
})
const [didHydrateState, setDidHydrateState] = useState(false)
@@ -274,6 +277,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
global: {},
})
const [includeTaskHistoryInEnhance, setIncludeTaskHistoryInEnhance] = useState(true)
+ const [showCloudPromotion, setShowCloudPromotion] = useState(true) // Default to true
const setListApiConfigMeta = useCallback(
(value: ProviderSettingsEntry[]) => setState((prevState) => ({ ...prevState, listApiConfigMeta: value })),
@@ -311,6 +315,10 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
if ((newState as any).includeTaskHistoryInEnhance !== undefined) {
setIncludeTaskHistoryInEnhance((newState as any).includeTaskHistoryInEnhance)
}
+ // Update showCloudPromotion if present in state message
+ if ((newState as any).showCloudPromotion !== undefined) {
+ setShowCloudPromotion((newState as any).showCloudPromotion)
+ }
// Handle marketplace data if present in state message
if (newState.marketplaceItems !== undefined) {
setMarketplaceItems(newState.marketplaceItems)
@@ -527,6 +535,11 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
},
includeTaskHistoryInEnhance,
setIncludeTaskHistoryInEnhance,
+ showCloudPromotion,
+ setShowCloudPromotion: (value) => {
+ setShowCloudPromotion(value)
+ setState((prevState) => ({ ...prevState, showCloudPromotion: value }))
+ },
}
return {children}