Преглед изворни кода

Add 'taking you to cloud' screen after provider welcome (#9652)

Matt Rubens пре 1 месец
родитељ
комит
520d4fb0be

+ 141 - 16
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<string | undefined>(undefined)
 	const [selectedProvider, setSelectedProvider] = useState<ProviderOption>("roo")
+	const [authInProgress, setAuthInProgress] = useState(false)
+	const [showManualEntry, setShowManualEntry] = useState(false)
+	const [manualUrl, setManualUrl] = useState("")
+	const manualUrlInputRef = useRef<HTMLInputElement | null>(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 (
+			<Tab>
+				<TabContent className="flex flex-col gap-4 p-6">
+					<div className="flex flex-col items-start gap-4 pt-8">
+						<VSCodeProgressRing className="size-6" />
+						<h2 className="mt-0 mb-0 text-lg font-semibold">{t("welcome:waitingForCloud.heading")}</h2>
+						<p className="text-sm text-vscode-descriptionForeground mt-0">
+							{t("welcome:waitingForCloud.description")}
+						</p>
+
+						<p className="text-sm text-vscode-descriptionForeground mt-2">
+							<Trans
+								i18nKey="welcome:waitingForCloud.noPrompt"
+								components={{
+									clickHere: (
+										<button
+											onClick={handleOpenSignupUrl}
+											className="text-vscode-textLink-foreground hover:text-vscode-textLink-activeForeground underline cursor-pointer bg-transparent border-none p-0 text-sm"
+										/>
+									),
+								}}
+							/>
+						</p>
+
+						<p className="text-sm text-vscode-descriptionForeground">
+							<Trans
+								i18nKey="welcome:waitingForCloud.havingTrouble"
+								components={{
+									clickHere: (
+										<button
+											onClick={() => setShowManualEntry(true)}
+											className="text-vscode-textLink-foreground hover:text-vscode-textLink-activeForeground underline cursor-pointer bg-transparent border-none p-0 text-sm"
+										/>
+									),
+								}}
+							/>
+						</p>
+
+						{showManualEntry && (
+							<div className="mt-2 w-full max-w-sm">
+								<p className="text-sm text-vscode-descriptionForeground mb-2">
+									{t("welcome:waitingForCloud.pasteUrl")}
+								</p>
+								<VSCodeTextField
+									ref={manualUrlInputRef as any}
+									value={manualUrl}
+									onChange={handleManualUrlChange}
+									onKeyDown={handleKeyDown}
+									placeholder="vscode://RooVeterinaryInc.roo-cline/auth/clerk/callback?state=..."
+									className="w-full"
+								/>
+							</div>
+						)}
+					</div>
+				</TabContent>
+				<div className="sticky bottom-0 bg-vscode-sideBar-background p-4 border-t border-vscode-panel-border">
+					<Button onClick={handleGoBack} variant="secondary" className="flex items-center gap-2">
+						<ArrowLeft className="size-4" />
+						{t("welcome:waitingForCloud.goBack")}
+					</Button>
+				</div>
+			</Tab>
+		)
+	}
+
 	return (
 		<Tab>
 			<TabContent className="flex flex-col gap-4 p-6">

+ 8 - 0
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, <clickHere>feu clic aquí</clickHere>.",
+		"havingTrouble": "Si has completat el registre però tens problemes, <clickHere>feu clic aquí</clickHere>.",
+		"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": {

+ 8 - 0
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, <clickHere>klick hier</clickHere>.",
+		"havingTrouble": "Wenn du die Anmeldung abgeschlossen hast, aber Probleme hast, <clickHere>klick hier</clickHere>.",
+		"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": {

+ 8 - 0
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, <clickHere>click here</clickHere>.",
+		"havingTrouble": "If you've completed the sign up but are having trouble, <clickHere>click here</clickHere>.",
+		"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": {

+ 8 - 0
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, <clickHere>haz clic aquí</clickHere>.",
+		"havingTrouble": "Si completaste el registro pero tienes problemas, <clickHere>haz clic aquí</clickHere>.",
+		"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": {

+ 8 - 0
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, <clickHere>clique ici</clickHere>.",
+		"havingTrouble": "Si tu as terminé l'inscription mais que tu rencontres des problèmes, <clickHere>clique ici</clickHere>.",
+		"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": {

+ 8 - 0
webview-ui/src/i18n/locales/hi/welcome.json

@@ -25,6 +25,14 @@
 		"useAnotherProviderDescription": "एक API कुंजी दर्ज करें और शुरू करें।",
 		"getStarted": "शुरू करें"
 	},
+	"waitingForCloud": {
+		"heading": "आपको Roo Code Cloud पर ले जा रहे हैं...",
+		"description": "अपने ब्राउज़र में साइन अप पूरा करें और आप स्वचालित रूप से यहां वापस आ जाएंगे।",
+		"noPrompt": "यदि आपको URL खोलने के लिए संकेत नहीं मिलता है, तो <clickHere>यहां क्लिक करें</clickHere>।",
+		"havingTrouble": "यदि आपने साइन अप पूरा कर लिया है लेकिन समस्या हो रही है, तो <clickHere>यहां क्लिक करें</clickHere>।",
+		"pasteUrl": "अपने ब्राउज़र से कॉलबैक URL पेस्ट करें:",
+		"goBack": "वापस जाएं"
+	},
 	"startRouter": "हम एक LLM राउटर का उपयोग करने की सलाह देते हैं:",
 	"startCustom": "या आप अपनी खुद की API कुंजी ला सकते हैं:",
 	"telemetry": {

+ 8 - 0
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, <clickHere>klik di sini</clickHere>.",
+		"havingTrouble": "Jika kamu telah menyelesaikan pendaftaran tetapi mengalami masalah, <clickHere>klik di sini</clickHere>.",
+		"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": {

+ 8 - 0
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, <clickHere>fai clic qui</clickHere>.",
+		"havingTrouble": "Se hai completato l'iscrizione ma hai problemi, <clickHere>fai clic qui</clickHere>.",
+		"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": {

+ 8 - 0
webview-ui/src/i18n/locales/ja/welcome.json

@@ -25,6 +25,14 @@
 		"useAnotherProviderDescription": "APIキーを入力して始める。",
 		"getStarted": "始める"
 	},
+	"waitingForCloud": {
+		"heading": "Roo Code Cloudにお連れします...",
+		"description": "ブラウザでサインアップを完了すると、自動的にここに戻ります。",
+		"noPrompt": "URLを開くように促されない場合は、<clickHere>ここをクリック</clickHere>してください。",
+		"havingTrouble": "サインアップを完了しましたが問題がある場合は、<clickHere>ここをクリック</clickHere>してください。",
+		"pasteUrl": "ブラウザからコールバックURLを貼り付けてください:",
+		"goBack": "戻る"
+	},
 	"startRouter": "LLMルーターの使用をお勧めします:",
 	"startCustom": "または、あなた自身のAPIキーを使用できます:",
 	"telemetry": {

+ 8 - 0
webview-ui/src/i18n/locales/ko/welcome.json

@@ -25,6 +25,14 @@
 		"useAnotherProviderDescription": "API 키를 입력하고 시작하세요.",
 		"getStarted": "시작하기"
 	},
+	"waitingForCloud": {
+		"heading": "Roo Code Cloud로 이동 중입니다...",
+		"description": "브라우저에서 가입을 완료하면 자동으로 여기로 돌아옵니다.",
+		"noPrompt": "URL을 열도록 요청받지 않으면 <clickHere>여기를 클릭</clickHere>하세요.",
+		"havingTrouble": "가입을 완료했지만 문제가 있으면 <clickHere>여기를 클릭</clickHere>하세요.",
+		"pasteUrl": "브라우저에서 콜백 URL을 붙여넣으세요:",
+		"goBack": "돌아가기"
+	},
 	"startRouter": "LLM 라우터 사용을 권장합니다:",
 	"startCustom": "또는 직접 API 키를 가져올 수 있습니다:",
 	"telemetry": {

+ 8 - 0
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, <clickHere>klik hier</clickHere>.",
+		"havingTrouble": "Als je de registratie hebt voltooid maar problemen hebt, <clickHere>klik hier</clickHere>.",
+		"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": {

+ 8 - 0
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, <clickHere>kliknij tutaj</clickHere>.",
+		"havingTrouble": "Jeśli ukończyłeś rejestrację, ale masz problemy, <clickHere>kliknij tutaj</clickHere>.",
+		"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": {

+ 8 - 0
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, <clickHere>clique aqui</clickHere>.",
+		"havingTrouble": "Se você completou o registro mas está tendo problemas, <clickHere>clique aqui</clickHere>.",
+		"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": {

+ 8 - 0
webview-ui/src/i18n/locales/ru/welcome.json

@@ -25,6 +25,14 @@
 		"useAnotherProviderDescription": "Введи API-ключ и начни.",
 		"getStarted": "Начать"
 	},
+	"waitingForCloud": {
+		"heading": "Направляем тебя в Roo Code Cloud...",
+		"description": "Завершите регистрацию в браузере, и вы автоматически вернетесь сюда.",
+		"noPrompt": "Если вас не попросят открыть URL, <clickHere>нажмите здесь</clickHere>.",
+		"havingTrouble": "Если вы завершили регистрацию, но у вас возникли проблемы, <clickHere>нажмите здесь</clickHere>.",
+		"pasteUrl": "Вставьте URL обратного вызова из браузера:",
+		"goBack": "Назад"
+	},
 	"startRouter": "Мы рекомендуем использовать маршрутизатор LLM:",
 	"startCustom": "Или вы можете использовать свой собственный API-ключ:",
 	"telemetry": {

+ 8 - 0
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, <clickHere>buraya tıkla</clickHere>.",
+		"havingTrouble": "Kaydı tamamladıysan ama sorun yaşıyorsan, <clickHere>buraya tıkla</clickHere>.",
+		"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": {

+ 8 - 0
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, <clickHere>hãy nhấp vào đây</clickHere>.",
+		"havingTrouble": "Nếu bạn đã hoàn thành đăng ký nhưng gặp sự cố, <clickHere>hãy nhấp vào đây</clickHere>.",
+		"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": {

+ 8 - 0
webview-ui/src/i18n/locales/zh-CN/welcome.json

@@ -25,6 +25,14 @@
 		"useAnotherProviderDescription": "输入 API 密钥即可开始。",
 		"getStarted": "开始使用"
 	},
+	"waitingForCloud": {
+		"heading": "正在跳转到 Roo Code Cloud...",
+		"description": "在浏览器中完成注册,随后你将自动返回此处。",
+		"noPrompt": "如果你未被提示打开 URL,<clickHere>请点击此处</clickHere>。",
+		"havingTrouble": "如果你已完成注册但遇到问题,<clickHere>请点击此处</clickHere>。",
+		"pasteUrl": "从浏览器粘贴回调 URL:",
+		"goBack": "返回"
+	},
 	"startRouter": "我们推荐使用 LLM 路由器:",
 	"startCustom": "或者你可以使用自己的 API 密钥:",
 	"telemetry": {

+ 8 - 0
webview-ui/src/i18n/locales/zh-TW/welcome.json

@@ -25,6 +25,14 @@
 		"useAnotherProviderDescription": "輸入 API 金鑰即可開始。",
 		"getStarted": "開始使用"
 	},
+	"waitingForCloud": {
+		"heading": "正在帶您前往 Roo Code Cloud...",
+		"description": "在瀏覽器中完成註冊,您將自動返回此處。",
+		"noPrompt": "如果您未被提示開啟 URL,<clickHere>請點擊此處</clickHere>。",
+		"havingTrouble": "如果您已完成註冊但遇到問題,<clickHere>請點擊此處</clickHere>。",
+		"pasteUrl": "從瀏覽器貼上回呼 URL:",
+		"goBack": "返回"
+	},
 	"startRouter": "我們建議使用 LLM 路由器:",
 	"startCustom": "或者您可以使用自己的 API 金鑰:",
 	"telemetry": {