diff --git a/webview-ui/src/components/welcome/WelcomeViewProvider.tsx b/webview-ui/src/components/welcome/WelcomeViewProvider.tsx index 2750f2db07f..40b8e5ca660 100644 --- a/webview-ui/src/components/welcome/WelcomeViewProvider.tsx +++ b/webview-ui/src/components/welcome/WelcomeViewProvider.tsx @@ -1,5 +1,5 @@ -import { useCallback, useState } from "react" -import { VSCodeLink } from "@vscode/webview-ui-toolkit/react" +import { useCallback, useEffect, useRef, useState } from "react" +import { VSCodeLink, VSCodeProgressRing, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" import type { ProviderSettings } from "@roo-code/types" @@ -14,14 +14,47 @@ import { Tab, TabContent } from "../common/Tab" import RooHero from "./RooHero" import { Trans } from "react-i18next" +import { ArrowLeft } from "lucide-react" type ProviderOption = "roo" | "custom" const WelcomeViewProvider = () => { - const { apiConfiguration, currentApiConfigName, setApiConfiguration, uriScheme } = useExtensionState() + const { apiConfiguration, currentApiConfigName, setApiConfiguration, uriScheme, cloudIsAuthenticated } = + useExtensionState() const { t } = useAppTranslation() const [errorMessage, setErrorMessage] = useState(undefined) const [selectedProvider, setSelectedProvider] = useState("roo") + const [authInProgress, setAuthInProgress] = useState(false) + const [showManualEntry, setShowManualEntry] = useState(false) + const [manualUrl, setManualUrl] = useState("") + const manualUrlInputRef = useRef(null) + + // When auth completes during the provider signup flow, save the Roo config + // This will cause showWelcome to become false and navigate to chat + useEffect(() => { + if (cloudIsAuthenticated && authInProgress) { + // Auth completed from provider signup flow - save the config now + const rooConfig: ProviderSettings = { + apiProvider: "roo", + } + vscode.postMessage({ + type: "upsertApiConfiguration", + text: currentApiConfigName, + apiConfiguration: rooConfig, + }) + setAuthInProgress(false) + setShowManualEntry(false) + } + }, [cloudIsAuthenticated, authInProgress, currentApiConfigName]) + + // Focus the manual URL input when it becomes visible + useEffect(() => { + if (showManualEntry && manualUrlInputRef.current) { + setTimeout(() => { + manualUrlInputRef.current?.focus() + }, 50) + } + }, [showManualEntry]) // Memoize the setApiConfigurationField function to pass to ApiOptions const setApiConfigurationFieldForApiOptions = useCallback( @@ -33,20 +66,14 @@ const WelcomeViewProvider = () => { const handleGetStarted = useCallback(() => { if (selectedProvider === "roo") { - // 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 with provider signup flow + // Trigger cloud sign-in with provider signup flow + // NOTE: We intentionally do NOT save the API configuration yet. + // The configuration will be saved by the extension after auth completes. + // This keeps showWelcome true so we can show the waiting state. vscode.postMessage({ type: "rooCloudSignIn", useProviderSignup: true }) + + // Show the waiting state + setAuthInProgress(true) } else { // Use custom provider - validate first const error = apiConfiguration ? validateApiConfiguration(apiConfiguration) : undefined @@ -61,6 +88,104 @@ const WelcomeViewProvider = () => { } }, [selectedProvider, apiConfiguration, currentApiConfigName]) + const handleGoBack = useCallback(() => { + setAuthInProgress(false) + setShowManualEntry(false) + setManualUrl("") + }, []) + + const handleManualUrlChange = (e: any) => { + const url = e.target.value + setManualUrl(url) + + // Auto-trigger authentication when a complete URL is pasted + setTimeout(() => { + if (url.trim() && url.includes("://") && url.includes("/auth/clerk/callback")) { + vscode.postMessage({ type: "rooCloudManualUrl", text: url.trim() }) + } + }, 100) + } + + const handleKeyDown = (e: any) => { + if (e.key === "Enter") { + const url = manualUrl.trim() + if (url && url.includes("://") && url.includes("/auth/clerk/callback")) { + vscode.postMessage({ type: "rooCloudManualUrl", text: url }) + } + } + } + + const handleOpenSignupUrl = () => { + vscode.postMessage({ type: "rooCloudSignIn", useProviderSignup: true }) + } + + // Render the waiting for cloud state + if (authInProgress) { + return ( + + +
+ +

{t("welcome:waitingForCloud.heading")}

+

+ {t("welcome:waitingForCloud.description")} +

+ +

+ + ), + }} + /> +

+ +

+ setShowManualEntry(true)} + className="text-vscode-textLink-foreground hover:text-vscode-textLink-activeForeground underline cursor-pointer bg-transparent border-none p-0 text-sm" + /> + ), + }} + /> +

+ + {showManualEntry && ( +
+

+ {t("welcome:waitingForCloud.pasteUrl")} +

+ +
+ )} +
+
+
+ +
+
+ ) + } + return ( diff --git a/webview-ui/src/i18n/locales/ca/welcome.json b/webview-ui/src/i18n/locales/ca/welcome.json index 60246050c95..08bface0921 100644 --- a/webview-ui/src/i18n/locales/ca/welcome.json +++ b/webview-ui/src/i18n/locales/ca/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Introdueix una clau API i comença.", "getStarted": "Començar" }, + "waitingForCloud": { + "heading": "Et portem a Roo Code Cloud...", + "description": "Completa el registre al navegador i tornaràs aquí automàticament.", + "noPrompt": "Si no se t'avisa per obrir una URL, feu clic aquí.", + "havingTrouble": "Si has completat el registre però tens problemes, feu clic aquí.", + "pasteUrl": "Enganxa la URL de resposta del teu navegador:", + "goBack": "Enrere" + }, "startRouter": "Recomanem utilitzar un router LLM:", "startCustom": "O pots utilitzar la teva pròpia clau API:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/de/welcome.json b/webview-ui/src/i18n/locales/de/welcome.json index 9bc91118d21..78304f0ca26 100644 --- a/webview-ui/src/i18n/locales/de/welcome.json +++ b/webview-ui/src/i18n/locales/de/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Gib einen API-Schlüssel ein und leg los.", "getStarted": "Loslegen" }, + "waitingForCloud": { + "heading": "Wir bringen dich zu Roo Code Cloud...", + "description": "Schließe die Anmeldung in deinem Browser ab und du wirst automatisch hierher zurückgebracht.", + "noPrompt": "Wenn du nicht aufgefordert wirst, eine URL zu öffnen, klick hier.", + "havingTrouble": "Wenn du die Anmeldung abgeschlossen hast, aber Probleme hast, klick hier.", + "pasteUrl": "Füge die Callback-URL aus deinem Browser ein:", + "goBack": "Zurück" + }, "startRouter": "Wir empfehlen die Verwendung eines LLM-Routers:", "startCustom": "Oder du kannst deinen eigenen API-Schlüssel verwenden:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/en/welcome.json b/webview-ui/src/i18n/locales/en/welcome.json index 705bc92cb7e..d5e0ec0739e 100644 --- a/webview-ui/src/i18n/locales/en/welcome.json +++ b/webview-ui/src/i18n/locales/en/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Enter an API key and get going.", "getStarted": "Get started" }, + "waitingForCloud": { + "heading": "Taking you to Roo Code Cloud...", + "description": "Complete sign-up in your browser, then you'll return here automatically.", + "noPrompt": "If you don't get prompted to open a URL, click here.", + "havingTrouble": "If you've completed the sign up but are having trouble, click here.", + "pasteUrl": "Paste the callback URL from your browser:", + "goBack": "Go back" + }, "startRouter": "We recommend using an LLM Router:", "startCustom": "Or you can bring your provider API key:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/es/welcome.json b/webview-ui/src/i18n/locales/es/welcome.json index 9f790919073..04f559081d8 100644 --- a/webview-ui/src/i18n/locales/es/welcome.json +++ b/webview-ui/src/i18n/locales/es/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Introduce una clave API y comienza.", "getStarted": "Comenzar" }, + "waitingForCloud": { + "heading": "Te llevamos a Roo Code Cloud...", + "description": "Completa el registro en tu navegador y volverás aquí automáticamente.", + "noPrompt": "Si no se te pide que abras una URL, haz clic aquí.", + "havingTrouble": "Si completaste el registro pero tienes problemas, haz clic aquí.", + "pasteUrl": "Pega la URL de respuesta de tu navegador:", + "goBack": "Volver" + }, "startRouter": "Recomendamos usar un router LLM:", "startCustom": "O puedes traer tu propia clave API:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/fr/welcome.json b/webview-ui/src/i18n/locales/fr/welcome.json index a61e577494c..733b22e1f44 100644 --- a/webview-ui/src/i18n/locales/fr/welcome.json +++ b/webview-ui/src/i18n/locales/fr/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Entre une clé API et commence.", "getStarted": "Commencer" }, + "waitingForCloud": { + "heading": "Nous te menons à Roo Code Cloud...", + "description": "Termine l'inscription dans ton navigateur et tu reviendras ici automatiquement.", + "noPrompt": "Si tu n'es pas invité à ouvrir une URL, clique ici.", + "havingTrouble": "Si tu as terminé l'inscription mais que tu rencontres des problèmes, clique ici.", + "pasteUrl": "Colle l'URL de rappel depuis ton navigateur :", + "goBack": "Retour" + }, "startRouter": "Nous recommandons d'utiliser un routeur LLM :", "startCustom": "Ou tu peux apporter ta propre clé API :", "telemetry": { diff --git a/webview-ui/src/i18n/locales/hi/welcome.json b/webview-ui/src/i18n/locales/hi/welcome.json index 196b98bad1f..af58fa50599 100644 --- a/webview-ui/src/i18n/locales/hi/welcome.json +++ b/webview-ui/src/i18n/locales/hi/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "एक API कुंजी दर्ज करें और शुरू करें।", "getStarted": "शुरू करें" }, + "waitingForCloud": { + "heading": "आपको Roo Code Cloud पर ले जा रहे हैं...", + "description": "अपने ब्राउज़र में साइन अप पूरा करें और आप स्वचालित रूप से यहां वापस आ जाएंगे।", + "noPrompt": "यदि आपको URL खोलने के लिए संकेत नहीं मिलता है, तो यहां क्लिक करें।", + "havingTrouble": "यदि आपने साइन अप पूरा कर लिया है लेकिन समस्या हो रही है, तो यहां क्लिक करें।", + "pasteUrl": "अपने ब्राउज़र से कॉलबैक URL पेस्ट करें:", + "goBack": "वापस जाएं" + }, "startRouter": "हम एक LLM राउटर का उपयोग करने की सलाह देते हैं:", "startCustom": "या आप अपनी खुद की API कुंजी ला सकते हैं:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/id/welcome.json b/webview-ui/src/i18n/locales/id/welcome.json index 5cf609f7089..88903f858d2 100644 --- a/webview-ui/src/i18n/locales/id/welcome.json +++ b/webview-ui/src/i18n/locales/id/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Masukkan kunci API dan mulai.", "getStarted": "Mulai" }, + "waitingForCloud": { + "heading": "Membawamu ke Roo Code Cloud...", + "description": "Selesaikan pendaftaran di browser dan kamu akan secara otomatis kembali ke sini.", + "noPrompt": "Jika kamu tidak diminta untuk membuka URL, klik di sini.", + "havingTrouble": "Jika kamu telah menyelesaikan pendaftaran tetapi mengalami masalah, klik di sini.", + "pasteUrl": "Tempel URL callback dari browser Anda:", + "goBack": "Kembali" + }, "startRouter": "Kami merekomendasikan menggunakan Router LLM:", "startCustom": "Atau Anda dapat menggunakan API key Anda sendiri:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/it/welcome.json b/webview-ui/src/i18n/locales/it/welcome.json index af185e63f1e..e0329c2b0d6 100644 --- a/webview-ui/src/i18n/locales/it/welcome.json +++ b/webview-ui/src/i18n/locales/it/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Inserisci una chiave API e inizia.", "getStarted": "Inizia" }, + "waitingForCloud": { + "heading": "Ti stiamo portando a Roo Code Cloud...", + "description": "Completa l'iscrizione nel tuo browser e tornerai qui automaticamente.", + "noPrompt": "Se non ti viene chiesto di aprire un URL, fai clic qui.", + "havingTrouble": "Se hai completato l'iscrizione ma hai problemi, fai clic qui.", + "pasteUrl": "Incolla l'URL di callback dal tuo browser:", + "goBack": "Indietro" + }, "startRouter": "Consigliamo di utilizzare un router LLM:", "startCustom": "Oppure puoi utilizzare la tua chiave API:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/ja/welcome.json b/webview-ui/src/i18n/locales/ja/welcome.json index 5b10eb6cdc5..c54253bf92b 100644 --- a/webview-ui/src/i18n/locales/ja/welcome.json +++ b/webview-ui/src/i18n/locales/ja/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "APIキーを入力して始める。", "getStarted": "始める" }, + "waitingForCloud": { + "heading": "Roo Code Cloudにお連れします...", + "description": "ブラウザでサインアップを完了すると、自動的にここに戻ります。", + "noPrompt": "URLを開くように促されない場合は、ここをクリックしてください。", + "havingTrouble": "サインアップを完了しましたが問題がある場合は、ここをクリックしてください。", + "pasteUrl": "ブラウザからコールバックURLを貼り付けてください:", + "goBack": "戻る" + }, "startRouter": "LLMルーターの使用をお勧めします:", "startCustom": "または、あなた自身のAPIキーを使用できます:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/ko/welcome.json b/webview-ui/src/i18n/locales/ko/welcome.json index f8a061430bc..7cf01158084 100644 --- a/webview-ui/src/i18n/locales/ko/welcome.json +++ b/webview-ui/src/i18n/locales/ko/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "API 키를 입력하고 시작하세요.", "getStarted": "시작하기" }, + "waitingForCloud": { + "heading": "Roo Code Cloud로 이동 중입니다...", + "description": "브라우저에서 가입을 완료하면 자동으로 여기로 돌아옵니다.", + "noPrompt": "URL을 열도록 요청받지 않으면 여기를 클릭하세요.", + "havingTrouble": "가입을 완료했지만 문제가 있으면 여기를 클릭하세요.", + "pasteUrl": "브라우저에서 콜백 URL을 붙여넣으세요:", + "goBack": "돌아가기" + }, "startRouter": "LLM 라우터 사용을 권장합니다:", "startCustom": "또는 직접 API 키를 가져올 수 있습니다:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/nl/welcome.json b/webview-ui/src/i18n/locales/nl/welcome.json index 8412896a74a..a52d139fb40 100644 --- a/webview-ui/src/i18n/locales/nl/welcome.json +++ b/webview-ui/src/i18n/locales/nl/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Voer een API-sleutel in en ga aan de slag.", "getStarted": "Beginnen" }, + "waitingForCloud": { + "heading": "We brengen je naar Roo Code Cloud...", + "description": "Voltooi de registratie in je browser en je keert automatisch hier terug.", + "noPrompt": "Als je niet wordt gevraagd een URL te openen, klik hier.", + "havingTrouble": "Als je de registratie hebt voltooid maar problemen hebt, klik hier.", + "pasteUrl": "Plak de callback-URL vanuit je browser:", + "goBack": "Terug" + }, "startRouter": "We raden aan om een LLM-router te gebruiken:", "startCustom": "Of je kunt je eigen API-sleutel gebruiken:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/pl/welcome.json b/webview-ui/src/i18n/locales/pl/welcome.json index a16b2b59dc0..6dc8fd169aa 100644 --- a/webview-ui/src/i18n/locales/pl/welcome.json +++ b/webview-ui/src/i18n/locales/pl/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Wprowadź klucz API i zacznij.", "getStarted": "Rozpocznij" }, + "waitingForCloud": { + "heading": "Zabieramy cię do Roo Code Cloud...", + "description": "Ukończ rejestrację w przeglądarce i automatycznie wrócisz tutaj.", + "noPrompt": "Jeśli nie zostaniesz poproszony o otwarcie adresu URL, kliknij tutaj.", + "havingTrouble": "Jeśli ukończyłeś rejestrację, ale masz problemy, kliknij tutaj.", + "pasteUrl": "Wklej adres URL wywołania zwrotnego z przeglądarki:", + "goBack": "Wróć" + }, "startRouter": "Zalecamy korzystanie z routera LLM:", "startCustom": "Lub możesz użyć własnego klucza API:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/pt-BR/welcome.json b/webview-ui/src/i18n/locales/pt-BR/welcome.json index 6ac5c2cc2c2..230cb0a2da8 100644 --- a/webview-ui/src/i18n/locales/pt-BR/welcome.json +++ b/webview-ui/src/i18n/locales/pt-BR/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Digite uma chave API e comece.", "getStarted": "Começar" }, + "waitingForCloud": { + "heading": "Levando você para Roo Code Cloud...", + "description": "Conclua o registro no seu navegador e você retornará aqui automaticamente.", + "noPrompt": "Se você não for solicitado a abrir uma URL, clique aqui.", + "havingTrouble": "Se você completou o registro mas está tendo problemas, clique aqui.", + "pasteUrl": "Cole a URL de callback do seu navegador:", + "goBack": "Voltar" + }, "startRouter": "Recomendamos usar um roteador LLM:", "startCustom": "Ou você pode trazer sua própria chave API:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/ru/welcome.json b/webview-ui/src/i18n/locales/ru/welcome.json index d83ab8399a9..97556b78af8 100644 --- a/webview-ui/src/i18n/locales/ru/welcome.json +++ b/webview-ui/src/i18n/locales/ru/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Введи API-ключ и начни.", "getStarted": "Начать" }, + "waitingForCloud": { + "heading": "Направляем тебя в Roo Code Cloud...", + "description": "Завершите регистрацию в браузере, и вы автоматически вернетесь сюда.", + "noPrompt": "Если вас не попросят открыть URL, нажмите здесь.", + "havingTrouble": "Если вы завершили регистрацию, но у вас возникли проблемы, нажмите здесь.", + "pasteUrl": "Вставьте URL обратного вызова из браузера:", + "goBack": "Назад" + }, "startRouter": "Мы рекомендуем использовать маршрутизатор LLM:", "startCustom": "Или вы можете использовать свой собственный API-ключ:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/tr/welcome.json b/webview-ui/src/i18n/locales/tr/welcome.json index 291aafed806..233abf61661 100644 --- a/webview-ui/src/i18n/locales/tr/welcome.json +++ b/webview-ui/src/i18n/locales/tr/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Bir API anahtarı gir ve başla.", "getStarted": "Başla" }, + "waitingForCloud": { + "heading": "Seni Roo Code Cloud'a götürüyoruz...", + "description": "Tarayıcında kaydı tamamla ve otomatik olarak buraya döneceksin.", + "noPrompt": "URL açmanız istenmezse, buraya tıkla.", + "havingTrouble": "Kaydı tamamladıysan ama sorun yaşıyorsan, buraya tıkla.", + "pasteUrl": "Tarayıcınızdan geri arama URL'sini yapıştırın:", + "goBack": "Geri Dön" + }, "startRouter": "Bir LLM yönlendiricisi kullanmanı öneririz:", "startCustom": "Veya kendi API anahtarını kullanabilirsin:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/vi/welcome.json b/webview-ui/src/i18n/locales/vi/welcome.json index d406911d4c7..b3fb071ecdd 100644 --- a/webview-ui/src/i18n/locales/vi/welcome.json +++ b/webview-ui/src/i18n/locales/vi/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "Nhập khóa API và bắt đầu.", "getStarted": "Bắt đầu" }, + "waitingForCloud": { + "heading": "Đang đưa bạn đến Roo Code Cloud...", + "description": "Hoàn thành đăng ký trong trình duyệt và bạn sẽ tự động quay lại đây.", + "noPrompt": "Nếu bạn không được nhắc mở URL, hãy nhấp vào đây.", + "havingTrouble": "Nếu bạn đã hoàn thành đăng ký nhưng gặp sự cố, hãy nhấp vào đây.", + "pasteUrl": "Dán URL callback từ trình duyệt của bạn:", + "goBack": "Quay lại" + }, "startRouter": "Chúng tôi khuyên bạn nên sử dụng bộ định tuyến LLM:", "startCustom": "Hoặc bạn có thể sử dụng khóa API của riêng mình:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/zh-CN/welcome.json b/webview-ui/src/i18n/locales/zh-CN/welcome.json index 783cc342d8d..f21b35ca8a6 100644 --- a/webview-ui/src/i18n/locales/zh-CN/welcome.json +++ b/webview-ui/src/i18n/locales/zh-CN/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "输入 API 密钥即可开始。", "getStarted": "开始使用" }, + "waitingForCloud": { + "heading": "正在跳转到 Roo Code Cloud...", + "description": "在浏览器中完成注册,随后你将自动返回此处。", + "noPrompt": "如果你未被提示打开 URL,请点击此处。", + "havingTrouble": "如果你已完成注册但遇到问题,请点击此处。", + "pasteUrl": "从浏览器粘贴回调 URL:", + "goBack": "返回" + }, "startRouter": "我们推荐使用 LLM 路由器:", "startCustom": "或者你可以使用自己的 API 密钥:", "telemetry": { diff --git a/webview-ui/src/i18n/locales/zh-TW/welcome.json b/webview-ui/src/i18n/locales/zh-TW/welcome.json index b03ab1b1441..6d3fc0dca0f 100644 --- a/webview-ui/src/i18n/locales/zh-TW/welcome.json +++ b/webview-ui/src/i18n/locales/zh-TW/welcome.json @@ -25,6 +25,14 @@ "useAnotherProviderDescription": "輸入 API 金鑰即可開始。", "getStarted": "開始使用" }, + "waitingForCloud": { + "heading": "正在帶您前往 Roo Code Cloud...", + "description": "在瀏覽器中完成註冊,您將自動返回此處。", + "noPrompt": "如果您未被提示開啟 URL,請點擊此處。", + "havingTrouble": "如果您已完成註冊但遇到問題,請點擊此處。", + "pasteUrl": "從瀏覽器貼上回呼 URL:", + "goBack": "返回" + }, "startRouter": "我們建議使用 LLM 路由器:", "startCustom": "或者您可以使用自己的 API 金鑰:", "telemetry": {