Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/cloud/src/CloudService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,9 @@ export class CloudService extends EventEmitter<CloudServiceEvents> implements Di

// AuthService

public async login(): Promise<void> {
public async login(landingPageSlug?: string): Promise<void> {
this.ensureInitialized()
return this.authService!.login()
return this.authService!.login(landingPageSlug)
}

public async logout(): Promise<void> {
Expand Down
16 changes: 12 additions & 4 deletions packages/cloud/src/WebAuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,10 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> 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<void> {
public async login(landingPageSlug?: string): Promise<void> {
try {
const vscode = await importVscode()

Expand All @@ -267,11 +269,17 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> 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}`)
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/cloud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ export interface AuthService extends EventEmitter<AuthServiceEvents> {
broadcast(): void

// Authentication methods
login(): Promise<void>
login(landingPageSlug?: string): Promise<void>
logout(): Promise<void>
handleCallback(code: string | null, state: string | null, organizationId?: string | null): Promise<void>

Expand Down
2 changes: 1 addition & 1 deletion src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,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

Expand Down
11 changes: 11 additions & 0 deletions src/core/webview/webviewMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2302,6 +2302,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()
Expand Down
1 change: 1 addition & 0 deletions src/shared/WebviewMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export interface WebviewMessage {
| "hasOpenedModeSelector"
| "cloudButtonClicked"
| "rooCloudSignIn"
| "cloudLandingPageSignIn"
| "rooCloudSignOut"
| "rooCloudManualUrl"
| "condenseTaskContextRequest"
Expand Down
118 changes: 47 additions & 71 deletions webview-ui/src/components/chat/Announcement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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 (
<Dialog
Expand All @@ -44,71 +40,57 @@ const Announcement = ({ hideAnnouncement }: AnnouncementProps) => {
<DialogContent className="max-w-96">
<DialogHeader>
<DialogTitle>{t("chat:announcement.title", { version: Package.version })}</DialogTitle>
<DialogDescription>
<Trans
i18nKey="chat:announcement.description"
components={{
bold: <b />,
}}
/>
</DialogDescription>
</DialogHeader>
<div>
<ul className="space-y-2">
<li>
•{" "}
<Trans
i18nKey="chat:announcement.feature1"
components={{
bold: <b />,
}}
/>
</li>
<li>
•{" "}
<Trans
i18nKey="chat:announcement.feature2"
components={{
bold: <b />,
}}
/>
</li>
</ul>

<div className="mt-4">
<div className="mb-3">
<Trans
i18nKey="chat:announcement.learnMore"
i18nKey="chat:announcement.stealthModel.feature"
components={{
learnMoreLink: (
<VSCodeLink
href="https://docs.roocode.com/update-notes/v3.28.0#task-sync--roomote-control"
onClick={(e) => {
e.preventDefault()
window.postMessage(
{
type: "action",
action: "openExternal",
data: {
url: "https://docs.roocode.com/update-notes/v3.28.0#task-sync--roomote-control",
},
},
"*",
)
}}
/>
),
bold: <b />,
}}
/>
</div>

<p className="mt-3 text-sm text-vscode-descriptionForeground">
{t("chat:announcement.stealthModel.note")}
</p>

<div className="mt-4">
<Button
onClick={() => {
vscode.postMessage({ type: "openExternal", url: cloudUrl })
}}
className="w-full">
{t("chat:announcement.visitCloudButton")}
</Button>
{!cloudIsAuthenticated ? (
<Button
onClick={() => {
vscode.postMessage({
type: "cloudLandingPageSignIn",
text: "supernova",
})
}}
className="w-full">
{t("chat:announcement.stealthModel.connectButton")}
</Button>
) : (
<>
<p className="mb-3">
<Trans
i18nKey="chat:announcement.stealthModel.selectModel"
components={{
code: <code />,
}}
/>
</p>
<Button
onClick={() => {
setOpen(false)
hideAnnouncement()
vscode.postMessage({
type: "switchTab",
tab: "settings",
})
}}
className="w-full">
{t("chat:announcement.stealthModel.goToSettingsButton")}
</Button>
</>
)}
</div>

<div className="mt-4 text-sm text-center">
Expand All @@ -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
</VSCodeLink>
Expand All @@ -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
</VSCodeLink>
Expand All @@ -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
</VSCodeLink>
Expand Down
14 changes: 8 additions & 6 deletions webview-ui/src/i18n/locales/ca/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions webview-ui/src/i18n/locales/de/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions webview-ui/src/i18n/locales/en/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,14 @@
},
"announcement": {
"title": "🎉 Roo Code {{version}} Released",
"description": "Introducing <bold>Roo Code Cloud:</bold> Bringing the power of Roo beyond the IDE",
"feature1": "<bold>Track task progress from anywhere (Free):</bold> Get real-time updates on long-running tasks without being stuck in your IDE",
"feature2": "<bold>Control the Roo Extension remotely (Pro):</bold> Start, stop, and interact with tasks from a chat-based browser interface.",
"learnMore": "Ready to take control? Learn more <learnMoreLink>here</learnMoreLink>.",
"visitCloudButton": "Visit Roo Code Cloud",
"socialLinks": "Join us on <xLink>X</xLink>, <discordLink>Discord</discordLink>, or <redditLink>r/RooCode</redditLink>"
"stealthModel": {
"feature": "<bold>Limited-time FREE stealth model</bold> - 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 <code>roo/code-supernova</code> from the Roo Code Cloud provider in Settings to get started.",
"goToSettingsButton": "Go to Settings"
},
"socialLinks": "Join us on <xLink>X</xLink>, <discordLink>Discord</discordLink>, or <redditLink>r/RooCode</redditLink> 🚀"
},
"reasoning": {
"thinking": "Thinking",
Expand Down
14 changes: 8 additions & 6 deletions webview-ui/src/i18n/locales/es/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions webview-ui/src/i18n/locales/fr/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions webview-ui/src/i18n/locales/hi/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading