Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
26 changes: 8 additions & 18 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.

26 changes: 8 additions & 18 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
26 changes: 8 additions & 18 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.

Loading
Loading