diff --git a/autogpt_platform/backend/backend/api/features/v1.py b/autogpt_platform/backend/backend/api/features/v1.py index 62b532089c..09d3759a65 100644 --- a/autogpt_platform/backend/backend/api/features/v1.py +++ b/autogpt_platform/backend/backend/api/features/v1.py @@ -261,18 +261,36 @@ async def get_onboarding_agents( return await get_recommended_agents(user_id) +class OnboardingStatusResponse(pydantic.BaseModel): + """Response for onboarding status check.""" + + is_onboarding_enabled: bool + is_chat_enabled: bool + + @v1_router.get( "/onboarding/enabled", summary="Is onboarding enabled", tags=["onboarding", "public"], + response_model=OnboardingStatusResponse, ) async def is_onboarding_enabled( user_id: Annotated[str, Security(get_user_id)], -) -> bool: - # If chat is enabled for user, skip legacy onboarding - if await is_feature_enabled(Flag.CHAT, user_id, False): - return False - return await onboarding_enabled() +) -> OnboardingStatusResponse: + # Check if chat is enabled for user + is_chat_enabled = await is_feature_enabled(Flag.CHAT, user_id, False) + + # If chat is enabled, skip legacy onboarding + if is_chat_enabled: + return OnboardingStatusResponse( + is_onboarding_enabled=False, + is_chat_enabled=True, + ) + + return OnboardingStatusResponse( + is_onboarding_enabled=await onboarding_enabled(), + is_chat_enabled=False, + ) @v1_router.post( diff --git a/autogpt_platform/frontend/src/app/(no-navbar)/onboarding/page.tsx b/autogpt_platform/frontend/src/app/(no-navbar)/onboarding/page.tsx index 1ebfe6b87b..70d9783ccd 100644 --- a/autogpt_platform/frontend/src/app/(no-navbar)/onboarding/page.tsx +++ b/autogpt_platform/frontend/src/app/(no-navbar)/onboarding/page.tsx @@ -2,8 +2,9 @@ import { LoadingSpinner } from "@/components/atoms/LoadingSpinner/LoadingSpinner"; import { useRouter } from "next/navigation"; import { useEffect } from "react"; -import { resolveResponse, shouldShowOnboarding } from "@/app/api/helpers"; +import { resolveResponse, getOnboardingStatus } from "@/app/api/helpers"; import { getV1OnboardingState } from "@/app/api/__generated__/endpoints/onboarding/onboarding"; +import { getHomepageRoute } from "@/lib/constants"; export default function OnboardingPage() { const router = useRouter(); @@ -11,10 +12,13 @@ export default function OnboardingPage() { useEffect(() => { async function redirectToStep() { try { - // Check if onboarding is enabled - const isEnabled = await shouldShowOnboarding(); - if (!isEnabled) { - router.replace("/"); + // Check if onboarding is enabled (also gets chat flag for redirect) + const { shouldShowOnboarding, isChatEnabled } = + await getOnboardingStatus(); + const homepageRoute = getHomepageRoute(isChatEnabled); + + if (!shouldShowOnboarding) { + router.replace(homepageRoute); return; } @@ -22,7 +26,7 @@ export default function OnboardingPage() { // Handle completed onboarding if (onboarding.completedSteps.includes("GET_RESULTS")) { - router.replace("/"); + router.replace(homepageRoute); return; } diff --git a/autogpt_platform/frontend/src/app/(platform)/auth/callback/route.ts b/autogpt_platform/frontend/src/app/(platform)/auth/callback/route.ts index a6a07a703f..15be137f63 100644 --- a/autogpt_platform/frontend/src/app/(platform)/auth/callback/route.ts +++ b/autogpt_platform/frontend/src/app/(platform)/auth/callback/route.ts @@ -1,8 +1,9 @@ import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase"; +import { getHomepageRoute } from "@/lib/constants"; import BackendAPI from "@/lib/autogpt-server-api"; import { NextResponse } from "next/server"; import { revalidatePath } from "next/cache"; -import { shouldShowOnboarding } from "@/app/api/helpers"; +import { getOnboardingStatus } from "@/app/api/helpers"; // Handle the callback to complete the user session login export async function GET(request: Request) { @@ -25,11 +26,15 @@ export async function GET(request: Request) { const api = new BackendAPI(); await api.createUser(); - if (await shouldShowOnboarding()) { + // Get onboarding status from backend (includes chat flag evaluated for this user) + const { shouldShowOnboarding, isChatEnabled } = + await getOnboardingStatus(); + if (shouldShowOnboarding) { next = "/onboarding"; revalidatePath("/onboarding", "layout"); } else { - revalidatePath("/", "layout"); + next = getHomepageRoute(isChatEnabled); + revalidatePath(next, "layout"); } } catch (createUserError) { console.error("Error creating user:", createUserError); diff --git a/autogpt_platform/frontend/src/app/(platform)/login/actions.ts b/autogpt_platform/frontend/src/app/(platform)/login/actions.ts index 936c879d69..447a25a41d 100644 --- a/autogpt_platform/frontend/src/app/(platform)/login/actions.ts +++ b/autogpt_platform/frontend/src/app/(platform)/login/actions.ts @@ -1,10 +1,11 @@ "use server"; +import { getHomepageRoute } from "@/lib/constants"; import BackendAPI from "@/lib/autogpt-server-api"; import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase"; import { loginFormSchema } from "@/types/auth"; import * as Sentry from "@sentry/nextjs"; -import { shouldShowOnboarding } from "../../api/helpers"; +import { getOnboardingStatus } from "../../api/helpers"; export async function login(email: string, password: string) { try { @@ -36,11 +37,15 @@ export async function login(email: string, password: string) { const api = new BackendAPI(); await api.createUser(); - const onboarding = await shouldShowOnboarding(); + // Get onboarding status from backend (includes chat flag evaluated for this user) + const { shouldShowOnboarding, isChatEnabled } = await getOnboardingStatus(); + const next = shouldShowOnboarding + ? "/onboarding" + : getHomepageRoute(isChatEnabled); return { success: true, - onboarding, + next, }; } catch (err) { Sentry.captureException(err); diff --git a/autogpt_platform/frontend/src/app/(platform)/login/useLoginPage.ts b/autogpt_platform/frontend/src/app/(platform)/login/useLoginPage.ts index 9bde570548..e64cc1858d 100644 --- a/autogpt_platform/frontend/src/app/(platform)/login/useLoginPage.ts +++ b/autogpt_platform/frontend/src/app/(platform)/login/useLoginPage.ts @@ -97,13 +97,8 @@ export function useLoginPage() { throw new Error(result.error || "Login failed"); } - if (nextUrl) { - router.replace(nextUrl); - } else if (result.onboarding) { - router.replace("/onboarding"); - } else { - router.replace(homepageRoute); - } + // Prefer URL's next parameter, then use backend-determined route + router.replace(nextUrl || result.next || homepageRoute); } catch (error) { toast({ title: diff --git a/autogpt_platform/frontend/src/app/(platform)/signup/actions.ts b/autogpt_platform/frontend/src/app/(platform)/signup/actions.ts index 6d68782e7a..0fbba54b8e 100644 --- a/autogpt_platform/frontend/src/app/(platform)/signup/actions.ts +++ b/autogpt_platform/frontend/src/app/(platform)/signup/actions.ts @@ -5,14 +5,13 @@ import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase"; import { signupFormSchema } from "@/types/auth"; import * as Sentry from "@sentry/nextjs"; import { isWaitlistError, logWaitlistError } from "../../api/auth/utils"; -import { shouldShowOnboarding } from "../../api/helpers"; +import { getOnboardingStatus } from "../../api/helpers"; export async function signup( email: string, password: string, confirmPassword: string, agreeToTerms: boolean, - isChatEnabled: boolean, ) { try { const parsed = signupFormSchema.safeParse({ @@ -59,8 +58,9 @@ export async function signup( await supabase.auth.setSession(data.session); } - const isOnboardingEnabled = await shouldShowOnboarding(); - const next = isOnboardingEnabled + // Get onboarding status from backend (includes chat flag evaluated for this user) + const { shouldShowOnboarding, isChatEnabled } = await getOnboardingStatus(); + const next = shouldShowOnboarding ? "/onboarding" : getHomepageRoute(isChatEnabled); diff --git a/autogpt_platform/frontend/src/app/(platform)/signup/useSignupPage.ts b/autogpt_platform/frontend/src/app/(platform)/signup/useSignupPage.ts index 5bd53ca846..5fa8c2c159 100644 --- a/autogpt_platform/frontend/src/app/(platform)/signup/useSignupPage.ts +++ b/autogpt_platform/frontend/src/app/(platform)/signup/useSignupPage.ts @@ -108,7 +108,6 @@ export function useSignupPage() { data.password, data.confirmPassword, data.agreeToTerms, - isChatEnabled === true, ); setIsLoading(false); diff --git a/autogpt_platform/frontend/src/app/api/helpers.ts b/autogpt_platform/frontend/src/app/api/helpers.ts index e9a708ba4c..c2104d231a 100644 --- a/autogpt_platform/frontend/src/app/api/helpers.ts +++ b/autogpt_platform/frontend/src/app/api/helpers.ts @@ -175,9 +175,12 @@ export async function resolveResponse< return res.data; } -export async function shouldShowOnboarding() { - const isEnabled = await resolveResponse(getV1IsOnboardingEnabled()); +export async function getOnboardingStatus() { + const status = await resolveResponse(getV1IsOnboardingEnabled()); const onboarding = await resolveResponse(getV1OnboardingState()); const isCompleted = onboarding.completedSteps.includes("CONGRATS"); - return isEnabled && !isCompleted; + return { + shouldShowOnboarding: status.is_onboarding_enabled && !isCompleted, + isChatEnabled: status.is_chat_enabled, + }; } diff --git a/autogpt_platform/frontend/src/app/api/openapi.json b/autogpt_platform/frontend/src/app/api/openapi.json index a6fdded27f..2a9db1990d 100644 --- a/autogpt_platform/frontend/src/app/api/openapi.json +++ b/autogpt_platform/frontend/src/app/api/openapi.json @@ -4525,8 +4525,7 @@ "content": { "application/json": { "schema": { - "type": "boolean", - "title": "Response Getv1Is Onboarding Enabled" + "$ref": "#/components/schemas/OnboardingStatusResponse" } } } @@ -8730,6 +8729,19 @@ "title": "OAuthApplicationPublicInfo", "description": "Public information about an OAuth application (for consent screen)" }, + "OnboardingStatusResponse": { + "properties": { + "is_onboarding_enabled": { + "type": "boolean", + "title": "Is Onboarding Enabled" + }, + "is_chat_enabled": { "type": "boolean", "title": "Is Chat Enabled" } + }, + "type": "object", + "required": ["is_onboarding_enabled", "is_chat_enabled"], + "title": "OnboardingStatusResponse", + "description": "Response for onboarding status check." + }, "OnboardingStep": { "type": "string", "enum": [