diff --git a/apps/web-roo-code/src/app/privacy/page.tsx b/apps/web-roo-code/src/app/privacy/page.tsx index 005bb8cb7c95..d4531e972037 100644 --- a/apps/web-roo-code/src/app/privacy/page.tsx +++ b/apps/web-roo-code/src/app/privacy/page.tsx @@ -290,6 +290,12 @@ export default function Privacy() { service‑related emails (such as password resets, billing notices, or security alerts) will continue even if you opt out. +
  • + Marketing communications: You can unsubscribe from marketing and + promotional emails by clicking the unsubscribe link in those emails. Transactional or + service‑related emails (such as password resets, billing notices, or security alerts) will + continue even if you opt out. +
  • 6. Security Practices

    diff --git a/packages/cloud/src/CloudService.ts b/packages/cloud/src/CloudService.ts index ce9e34de8ce6..9944055460d8 100644 --- a/packages/cloud/src/CloudService.ts +++ b/packages/cloud/src/CloudService.ts @@ -170,9 +170,9 @@ export class CloudService extends EventEmitter implements Di // AuthService - public async login(): Promise { + public async login(landingPageSlug?: string): Promise { this.ensureInitialized() - return this.authService!.login() + return this.authService!.login(landingPageSlug) } public async logout(): Promise { diff --git a/packages/cloud/src/WebAuthService.ts b/packages/cloud/src/WebAuthService.ts index 934ca90b71d4..3c57508403d2 100644 --- a/packages/cloud/src/WebAuthService.ts +++ b/packages/cloud/src/WebAuthService.ts @@ -248,8 +248,10 @@ export class WebAuthService extends EventEmitter implements A * * This method initiates the authentication flow by generating a state parameter * and opening the browser to the authorization URL. + * + * @param landingPageSlug Optional slug of a specific landing page (e.g., "supernova", "special-offer", etc.) */ - public async login(): Promise { + public async login(landingPageSlug?: string): Promise { try { const vscode = await importVscode() @@ -267,11 +269,17 @@ export class WebAuthService extends EventEmitter implements A state, auth_redirect: `${vscode.env.uriScheme}://${publisher}.${name}`, }) - const url = `${getRooCodeApiUrl()}/extension/sign-in?${params.toString()}` + + // Use landing page URL if slug is provided, otherwise use default sign-in URL + const url = landingPageSlug + ? `${getRooCodeApiUrl()}/l/${landingPageSlug}?${params.toString()}` + : `${getRooCodeApiUrl()}/extension/sign-in?${params.toString()}` + await vscode.env.openExternal(vscode.Uri.parse(url)) } catch (error) { - this.log(`[auth] Error initiating Roo Code Cloud auth: ${error}`) - throw new Error(`Failed to initiate Roo Code Cloud authentication: ${error}`) + const context = landingPageSlug ? ` (landing page: ${landingPageSlug})` : "" + this.log(`[auth] Error initiating Roo Code Cloud auth${context}: ${error}`) + throw new Error(`Failed to initiate Roo Code Cloud authentication${context}: ${error}`) } } diff --git a/packages/types/src/cloud.ts b/packages/types/src/cloud.ts index 7ffb28ae5d67..b56a67464b00 100644 --- a/packages/types/src/cloud.ts +++ b/packages/types/src/cloud.ts @@ -239,7 +239,7 @@ export interface AuthService extends EventEmitter { broadcast(): void // Authentication methods - login(): Promise + login(landingPageSlug?: string): Promise logout(): Promise handleCallback(code: string | null, state: string | null, organizationId?: string | null): Promise diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 281dac7f37dc..6ca718843cb8 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -152,7 +152,7 @@ export class ClineProvider public isViewLaunched = false public settingsImportedAt?: number - public readonly latestAnnouncementId = "sep-2025-roo-code-cloud" // Roo Code Cloud announcement + public readonly latestAnnouncementId = "sep-2025-code-supernova" // Code Supernova stealth model announcement public readonly providerSettingsManager: ProviderSettingsManager public readonly customModesManager: CustomModesManager diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index edd979c4f161..e13b5140a15e 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -2410,6 +2410,17 @@ export const webviewMessageHandler = async ( break } + case "cloudLandingPageSignIn": { + try { + const landingPageSlug = message.text || "supernova" + TelemetryService.instance.captureEvent(TelemetryEventName.AUTHENTICATION_INITIATED) + await CloudService.instance.login(landingPageSlug) + } catch (error) { + provider.log(`CloudService#login failed: ${error}`) + vscode.window.showErrorMessage("Sign in failed.") + } + break + } case "rooCloudSignOut": { try { await CloudService.instance.logout() diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index a31458a76455..ca6027ecbc04 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -182,6 +182,7 @@ export interface WebviewMessage { | "hasOpenedModeSelector" | "cloudButtonClicked" | "rooCloudSignIn" + | "cloudLandingPageSignIn" | "rooCloudSignOut" | "rooCloudManualUrl" | "condenseTaskContextRequest" diff --git a/webview-ui/src/components/chat/Announcement.tsx b/webview-ui/src/components/chat/Announcement.tsx index 8c52c41e42ff..cfe41340bc96 100644 --- a/webview-ui/src/components/chat/Announcement.tsx +++ b/webview-ui/src/components/chat/Announcement.tsx @@ -6,12 +6,9 @@ import { Package } from "@roo/package" import { useAppTranslation } from "@src/i18n/TranslationContext" import { useExtensionState } from "@src/context/ExtensionStateContext" import { vscode } from "@src/utils/vscode" -import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@src/components/ui" +import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@src/components/ui" import { Button } from "@src/components/ui" -// Define the production URL constant locally to avoid importing from cloud package in webview -const PRODUCTION_ROO_CODE_API_URL = "https://app.roocode.com" - interface AnnouncementProps { hideAnnouncement: () => void } @@ -28,8 +25,7 @@ interface AnnouncementProps { const Announcement = ({ hideAnnouncement }: AnnouncementProps) => { const { t } = useAppTranslation() const [open, setOpen] = useState(true) - const { cloudApiUrl } = useExtensionState() - const cloudUrl = cloudApiUrl || PRODUCTION_ROO_CODE_API_URL + const { cloudIsAuthenticated } = useExtensionState() return ( { {t("chat:announcement.title", { version: Package.version })} - - , - }} - /> -
    -
      -
    • - •{" "} - , - }} - /> -
    • -
    • - •{" "} - , - }} - /> -
    • -
    - -
    +
    { - e.preventDefault() - window.postMessage( - { - type: "action", - action: "openExternal", - data: { - url: "https://docs.roocode.com/update-notes/v3.28.0#task-sync--roomote-control", - }, - }, - "*", - ) - }} - /> - ), + bold: , }} />
    +

    + {t("chat:announcement.stealthModel.note")} +

    +
    - + {!cloudIsAuthenticated ? ( + + ) : ( + <> +

    + , + }} + /> +

    + + + )}
    @@ -132,7 +114,7 @@ const XLink = () => ( href="https://x.com/roo_code" onClick={(e) => { e.preventDefault() - window.postMessage({ type: "action", action: "openExternal", data: { url: "https://x.com/roo_code" } }, "*") + vscode.postMessage({ type: "openExternal", url: "https://x.com/roo_code" }) }}> X @@ -143,10 +125,7 @@ const DiscordLink = () => ( href="https://discord.gg/rCQcvT7Fnt" onClick={(e) => { e.preventDefault() - window.postMessage( - { type: "action", action: "openExternal", data: { url: "https://discord.gg/rCQcvT7Fnt" } }, - "*", - ) + vscode.postMessage({ type: "openExternal", url: "https://discord.gg/rCQcvT7Fnt" }) }}> Discord @@ -157,10 +136,7 @@ const RedditLink = () => ( href="https://www.reddit.com/r/RooCode/" onClick={(e) => { e.preventDefault() - window.postMessage( - { type: "action", action: "openExternal", data: { url: "https://www.reddit.com/r/RooCode/" } }, - "*", - ) + vscode.postMessage({ type: "openExternal", url: "https://www.reddit.com/r/RooCode/" }) }}> r/RooCode diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index a79966e5a562..6f86ea117284 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -293,12 +293,14 @@ }, "announcement": { "title": "🎉 Roo Code {{version}} Released", - "description": "Introducing Roo Code Cloud: Bringing the power of Roo beyond the IDE", - "feature1": "Track task progress from anywhere (Free): Get real-time updates on long-running tasks without being stuck in your IDE", - "feature2": "Control the Roo Extension remotely (Pro): Start, stop, and interact with tasks from a chat-based browser interface.", - "learnMore": "Ready to take control? Learn more here.", - "visitCloudButton": "Visit Roo Code Cloud", - "socialLinks": "Join us on X, Discord, or r/RooCode" + "stealthModel": { + "feature": "Limited-time FREE stealth model - Code Supernova: A versatile agentic coding model that supports image inputs, accessible through Roo Code Cloud.", + "note": "(Note: prompts and completions are logged by the model creator and used to improve the model)", + "connectButton": "Connect to Roo Code Cloud", + "selectModel": "Select roo/code-supernova from the Roo Code Cloud provider in Settings to get started.", + "goToSettingsButton": "Go to Settings" + }, + "socialLinks": "Join us on X, Discord, or r/RooCode 🚀" }, "reasoning": { "thinking": "Thinking", diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index 9898e783c77d..360d624b49e7 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -285,12 +285,14 @@ }, "announcement": { "title": "🎉 Roo Code {{version}} 已发布", - "description": "介绍 Roo Code Cloud:将 Roo 的强大功能扩展到 IDE 之外", - "feature1": "随时随地跟踪任务进度(免费):获取长时间运行任务的实时更新,无需困在 IDE 中", - "feature2": "远程控制 Roo 扩展(Pro):通过基于聊天的浏览器界面启动、停止和与任务交互。", - "learnMore": "准备掌控一切?在这里了解更多。", - "visitCloudButton": "访问 Roo Code Cloud", - "socialLinks": "在 XDiscordr/RooCode 上关注我们" + "stealthModel": { + "feature": "限时免费隐形模型 - Code Supernova:一个支持图像输入的多功能代理编程模型,通过 Roo Code Cloud 提供。", + "note": "(注意:提示词和补全内容会被模型创建者记录并用于改进模型)", + "connectButton": "连接到 Roo Code Cloud", + "selectModel": "在设置中从 Roo Code Cloud 提供商选择 roo/code-supernova 开始使用。", + "goToSettingsButton": "前往设置" + }, + "socialLinks": "在 XDiscordr/RooCode 上关注我们 🚀" }, "browser": { "rooWantsToUse": "Roo想使用浏览器", diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index d0f3853fab6a..dd570891b7da 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -294,12 +294,14 @@ }, "announcement": { "title": "🎉 Roo Code {{version}} 已發布", - "description": "介紹 Roo Code Cloud:將 Roo 的強大功能延伸到 IDE 之外", - "feature1": "隨時隨地追蹤任務進度(免費):取得長時間執行任務的即時更新,無需被困在 IDE 中", - "feature2": "遠端控制 Roo 擴充功能(Pro):透過基於聊天的瀏覽器介面啟動、停止並與任務互動。", - "learnMore": "準備好掌控一切了嗎?在這裡了解更多。", - "visitCloudButton": "造訪 Roo Code Cloud", - "socialLinks": "在 XDiscordr/RooCode 上關注我們" + "stealthModel": { + "feature": "限時免費隱形模型 - Code Supernova:一個支援圖像輸入的多功能代理程式編程模型,透過 Roo Code Cloud 提供。", + "note": "(注意:提示和完成會被模型創建者記錄並用於改進模型)", + "connectButton": "連接到 Roo Code Cloud", + "selectModel": "在設定中從 Roo Code Cloud 提供商選擇 roo/code-supernova 開始使用。", + "goToSettingsButton": "前往設定" + }, + "socialLinks": "在 XDiscordr/RooCode 上關注我們 🚀" }, "reasoning": { "thinking": "思考中",