diff --git a/packages/types/src/telemetry.ts b/packages/types/src/telemetry.ts index 81c20176ff5..abaceb9fbb0 100644 --- a/packages/types/src/telemetry.ts +++ b/packages/types/src/telemetry.ts @@ -61,6 +61,8 @@ export enum TelemetryEventName { ACCOUNT_LOGOUT_CLICKED = "Account Logout Clicked", ACCOUNT_LOGOUT_SUCCESS = "Account Logout Success", + FEATURED_PROVIDER_CLICKED = "Featured Provider Clicked", + UPSELL_DISMISSED = "Upsell Dismissed", UPSELL_CLICKED = "Upsell Clicked", @@ -184,6 +186,7 @@ export const rooCodeTelemetryEventSchema = z.discriminatedUnion("type", [ TelemetryEventName.ACCOUNT_CONNECT_SUCCESS, TelemetryEventName.ACCOUNT_LOGOUT_CLICKED, TelemetryEventName.ACCOUNT_LOGOUT_SUCCESS, + TelemetryEventName.FEATURED_PROVIDER_CLICKED, TelemetryEventName.UPSELL_DISMISSED, TelemetryEventName.UPSELL_CLICKED, TelemetryEventName.SCHEMA_VALIDATION_ERROR, diff --git a/src/assets/images/roo.png b/src/assets/images/roo.png new file mode 100644 index 00000000000..5dfc8723e83 Binary files /dev/null and b/src/assets/images/roo.png differ diff --git a/webview-ui/src/components/welcome/WelcomeView.tsx b/webview-ui/src/components/welcome/WelcomeView.tsx index 12ef319f92c..e2af5c93d41 100644 --- a/webview-ui/src/components/welcome/WelcomeView.tsx +++ b/webview-ui/src/components/welcome/WelcomeView.tsx @@ -1,15 +1,18 @@ -import { useCallback, useState } from "react" +import { useCallback, useState, useEffect } from "react" import knuthShuffle from "knuth-shuffle-seeded" import { Trans } from "react-i18next" import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react" +import posthog from "posthog-js" import type { ProviderSettings } from "@roo-code/types" +import { TelemetryEventName } from "@roo-code/types" import { useExtensionState } from "@src/context/ExtensionStateContext" import { validateApiConfiguration } from "@src/utils/validate" import { vscode } from "@src/utils/vscode" import { useAppTranslation } from "@src/i18n/TranslationContext" import { getRequestyAuthUrl, getOpenRouterAuthUrl } from "@src/oauth/urls" +import { telemetryClient } from "@src/utils/TelemetryClient" import ApiOptions from "../settings/ApiOptions" import { Tab, TabContent } from "../common/Tab" @@ -20,6 +23,14 @@ const WelcomeView = () => { const { apiConfiguration, currentApiConfigName, setApiConfiguration, uriScheme, machineId } = useExtensionState() const { t } = useAppTranslation() const [errorMessage, setErrorMessage] = useState(undefined) + const [showRooProvider, setShowRooProvider] = useState(false) + + // Check PostHog feature flag for Roo provider + useEffect(() => { + posthog.onFeatureFlags(function () { + setShowRooProvider(posthog?.getFeatureFlag("roo-provider-featured") === "test") + }) + }, []) // Memoize the setApiConfigurationField function to pass to ApiOptions const setApiConfigurationFieldForApiOptions = useCallback( @@ -69,7 +80,7 @@ const WelcomeView = () => { {/* Define the providers */} {(() => { // Provider card configuration - const providers = [ + const baseProviders = [ { slug: "requesty", name: "Requesty", @@ -85,6 +96,20 @@ const WelcomeView = () => { }, ] + // Conditionally add Roo provider based on feature flag + const providers = showRooProvider + ? [ + ...baseProviders, + { + slug: "roo", + name: "Roo Code Cloud", + description: t("welcome:routers.roo.description"), + incentive: t("welcome:routers.roo.incentive"), + authUrl: "#", // Placeholder since onClick handler will prevent default + }, + ] + : baseProviders + // Shuffle providers based on machine ID (will be consistent for the same machine) const orderedProviders = [...providers] knuthShuffle(orderedProviders, (machineId as any) || Date.now()) @@ -94,9 +119,41 @@ const WelcomeView = () => { + rel="noopener noreferrer" + onClick={(e) => { + // Track telemetry for featured provider click + telemetryClient.capture(TelemetryEventName.FEATURED_PROVIDER_CLICKED, { + provider: provider.slug, + }) + + // Special handling for Roo provider + if (provider.slug === "roo") { + e.preventDefault() + + // Set the Roo provider configuration + const rooConfig: ProviderSettings = { + apiProvider: "roo", + } + + // Save the Roo provider configuration + vscode.postMessage({ + type: "upsertApiConfiguration", + text: currentApiConfigName, + apiConfiguration: rooConfig, + }) + + // Then trigger cloud sign-in + vscode.postMessage({ type: "rooCloudSignIn" }) + } + // For other providers, let the default link behavior work + }}> + {provider.incentive && ( +
+ {provider.incentive} +
+ )}
{
{provider.name}
-
-
- {provider.description} -
- {provider.incentive && ( -
{provider.incentive}
- )} +
+ {provider.description}
diff --git a/webview-ui/src/i18n/locales/ca/welcome.json b/webview-ui/src/i18n/locales/ca/welcome.json index 4b3e75a3e16..c819a48a19d 100644 --- a/webview-ui/src/i18n/locales/ca/welcome.json +++ b/webview-ui/src/i18n/locales/ca/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Una interfície unificada per a LLMs" + }, + "roo": { + "description": "Els millors models gratuïts per començar", + "incentive": "Prova Roo gratis" } }, "chooseProvider": "Per fer la seva màgia, Roo necessita una clau API.", diff --git a/webview-ui/src/i18n/locales/de/welcome.json b/webview-ui/src/i18n/locales/de/welcome.json index 13cf9f8687f..a95ff103739 100644 --- a/webview-ui/src/i18n/locales/de/welcome.json +++ b/webview-ui/src/i18n/locales/de/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Eine einheitliche Schnittstelle für LLMs" + }, + "roo": { + "description": "Die besten kostenlosen Modelle für den Einstieg", + "incentive": "Probier Roo kostenlos aus" } }, "chooseProvider": "Um seine Magie zu entfalten, benötigt Roo einen API-Schlüssel.", diff --git a/webview-ui/src/i18n/locales/en/welcome.json b/webview-ui/src/i18n/locales/en/welcome.json index b19245fa8e1..5cb9b488dc3 100644 --- a/webview-ui/src/i18n/locales/en/welcome.json +++ b/webview-ui/src/i18n/locales/en/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "A unified interface for LLMs" + }, + "roo": { + "description": "The best free models to get started", + "incentive": "Try Roo out for free" } }, "chooseProvider": "To do its magic, Roo needs an API key.", diff --git a/webview-ui/src/i18n/locales/es/welcome.json b/webview-ui/src/i18n/locales/es/welcome.json index 2a3a80751a2..2f7217d4f3e 100644 --- a/webview-ui/src/i18n/locales/es/welcome.json +++ b/webview-ui/src/i18n/locales/es/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Una interfaz unificada para LLMs" + }, + "roo": { + "description": "Los mejores modelos gratuitos para empezar", + "incentive": "Prueba Roo gratis" } }, "chooseProvider": "Para hacer su magia, Roo necesita una clave API.", diff --git a/webview-ui/src/i18n/locales/fr/welcome.json b/webview-ui/src/i18n/locales/fr/welcome.json index 7c3ce18d651..a1e692bb844 100644 --- a/webview-ui/src/i18n/locales/fr/welcome.json +++ b/webview-ui/src/i18n/locales/fr/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Une interface unifiée pour les LLMs" + }, + "roo": { + "description": "Les meilleurs modèles gratuits pour commencer", + "incentive": "Essayez Roo gratuitement" } }, "chooseProvider": "Pour faire sa magie, Roo a besoin d'une clé API.", diff --git a/webview-ui/src/i18n/locales/hi/welcome.json b/webview-ui/src/i18n/locales/hi/welcome.json index 03dffc9052f..279f588d706 100644 --- a/webview-ui/src/i18n/locales/hi/welcome.json +++ b/webview-ui/src/i18n/locales/hi/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "LLMs के लिए एक एकीकृत इंटरफेस" + }, + "roo": { + "description": "शुरू करने के लिए सर्वोत्तम निःशुल्क मॉडल", + "incentive": "Roo को निःशुल्क आज़माएं" } }, "chooseProvider": "अपना जादू दिखाने के लिए, Roo को एक API कुंजी की आवश्यकता है।", diff --git a/webview-ui/src/i18n/locales/id/welcome.json b/webview-ui/src/i18n/locales/id/welcome.json index 49efa819e2f..73eacc3b1e0 100644 --- a/webview-ui/src/i18n/locales/id/welcome.json +++ b/webview-ui/src/i18n/locales/id/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Interface terpadu untuk LLM" + }, + "roo": { + "description": "Model gratis terbaik untuk memulai", + "incentive": "Coba Roo gratis" } }, "chooseProvider": "Untuk melakukan keajaibannya, Roo membutuhkan API key.", diff --git a/webview-ui/src/i18n/locales/it/welcome.json b/webview-ui/src/i18n/locales/it/welcome.json index 5bc96b045f4..46efe5ef625 100644 --- a/webview-ui/src/i18n/locales/it/welcome.json +++ b/webview-ui/src/i18n/locales/it/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Un'interfaccia unificata per LLMs" + }, + "roo": { + "description": "I migliori modelli gratuiti per iniziare", + "incentive": "Prova Roo gratuitamente" } }, "chooseProvider": "Per fare la sua magia, Roo ha bisogno di una chiave API.", diff --git a/webview-ui/src/i18n/locales/ja/welcome.json b/webview-ui/src/i18n/locales/ja/welcome.json index a1a13015b8c..946f6f23226 100644 --- a/webview-ui/src/i18n/locales/ja/welcome.json +++ b/webview-ui/src/i18n/locales/ja/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "LLMsのための統一インターフェース" + }, + "roo": { + "description": "始めるための最高の無料モデル", + "incentive": "Rooを無料で試す" } }, "chooseProvider": "Rooが機能するには、APIキーが必要です。", diff --git a/webview-ui/src/i18n/locales/ko/welcome.json b/webview-ui/src/i18n/locales/ko/welcome.json index bd00d8a2aa3..2f65841df47 100644 --- a/webview-ui/src/i18n/locales/ko/welcome.json +++ b/webview-ui/src/i18n/locales/ko/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "LLM을 위한 통합 인터페이스" + }, + "roo": { + "description": "시작하기에 최고의 무료 모델", + "incentive": "Roo를 무료로 체험해보세요" } }, "chooseProvider": "Roo가 작동하려면 API 키가 필요합니다.", diff --git a/webview-ui/src/i18n/locales/nl/welcome.json b/webview-ui/src/i18n/locales/nl/welcome.json index 625122816d2..912b38e3eea 100644 --- a/webview-ui/src/i18n/locales/nl/welcome.json +++ b/webview-ui/src/i18n/locales/nl/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Een uniforme interface voor LLM's" + }, + "roo": { + "description": "De beste gratis modellen om mee te beginnen", + "incentive": "Probeer Roo gratis uit" } }, "chooseProvider": "Om zijn magie te doen, heeft Roo een API-sleutel nodig.", diff --git a/webview-ui/src/i18n/locales/pl/welcome.json b/webview-ui/src/i18n/locales/pl/welcome.json index 7bddbac4cba..8e63cf9d8f5 100644 --- a/webview-ui/src/i18n/locales/pl/welcome.json +++ b/webview-ui/src/i18n/locales/pl/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Ujednolicony interfejs dla LLMs" + }, + "roo": { + "description": "Najlepsze darmowe modele na start", + "incentive": "Wypróbuj Roo za darmo" } }, "chooseProvider": "Aby działać, Roo potrzebuje klucza API.", diff --git a/webview-ui/src/i18n/locales/pt-BR/welcome.json b/webview-ui/src/i18n/locales/pt-BR/welcome.json index fced51060fb..489841a78f5 100644 --- a/webview-ui/src/i18n/locales/pt-BR/welcome.json +++ b/webview-ui/src/i18n/locales/pt-BR/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Uma interface unificada para LLMs" + }, + "roo": { + "description": "Os melhores modelos gratuitos para começar", + "incentive": "Experimente o Roo gratuitamente" } }, "chooseProvider": "Para fazer sua mágica, o Roo precisa de uma chave API.", diff --git a/webview-ui/src/i18n/locales/ru/welcome.json b/webview-ui/src/i18n/locales/ru/welcome.json index b8400444a00..978cfc066ba 100644 --- a/webview-ui/src/i18n/locales/ru/welcome.json +++ b/webview-ui/src/i18n/locales/ru/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Унифицированный интерфейс для LLM" + }, + "roo": { + "description": "Лучшие бесплатные модели для начала работы", + "incentive": "Попробуй Roo бесплатно" } }, "chooseProvider": "Для своей магии Roo нуждается в API-ключе.", diff --git a/webview-ui/src/i18n/locales/tr/welcome.json b/webview-ui/src/i18n/locales/tr/welcome.json index 7551676c6c4..ff79c4f98a1 100644 --- a/webview-ui/src/i18n/locales/tr/welcome.json +++ b/webview-ui/src/i18n/locales/tr/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "LLM'ler için birleşik bir arayüz" + }, + "roo": { + "description": "Başlamak için en iyi ücretsiz modeller", + "incentive": "Roo'yu ücretsiz dene" } }, "chooseProvider": "Sihirini yapabilmesi için Roo'nun bir API anahtarına ihtiyacı var.", diff --git a/webview-ui/src/i18n/locales/vi/welcome.json b/webview-ui/src/i18n/locales/vi/welcome.json index 275bc5039dd..6a6545c3abf 100644 --- a/webview-ui/src/i18n/locales/vi/welcome.json +++ b/webview-ui/src/i18n/locales/vi/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "Giao diện thống nhất cho các LLM" + }, + "roo": { + "description": "Những mô hình miễn phí tốt nhất để bắt đầu", + "incentive": "Dùng thử Roo miễn phí" } }, "chooseProvider": "Để thực hiện phép màu của mình, Roo cần một khóa API.", diff --git a/webview-ui/src/i18n/locales/zh-CN/welcome.json b/webview-ui/src/i18n/locales/zh-CN/welcome.json index a53adf08cd1..d4fe595e143 100644 --- a/webview-ui/src/i18n/locales/zh-CN/welcome.json +++ b/webview-ui/src/i18n/locales/zh-CN/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "统一了大语言模型的接口" + }, + "roo": { + "description": "最优秀的免费模型助你开始", + "incentive": "免费试用 Roo" } }, "chooseProvider": "Roo 需要一个 API 密钥才能发挥魔力。", diff --git a/webview-ui/src/i18n/locales/zh-TW/welcome.json b/webview-ui/src/i18n/locales/zh-TW/welcome.json index de1beb9ffe3..ed4526844bb 100644 --- a/webview-ui/src/i18n/locales/zh-TW/welcome.json +++ b/webview-ui/src/i18n/locales/zh-TW/welcome.json @@ -10,6 +10,10 @@ }, "openrouter": { "description": "LLM 的統一介面" + }, + "roo": { + "description": "最優秀的免費模型助你開始", + "incentive": "免費試用 Roo" } }, "chooseProvider": "Roo 需要 API 金鑰才能發揮魔力。",