Merge branch 'dev' into swiftyos/sdk

This commit is contained in:
Swifty
2025-07-02 17:26:15 +02:00
committed by GitHub
3 changed files with 86 additions and 20 deletions

View File

@@ -1,4 +1,5 @@
import {
ApiError,
makeAuthenticatedFileUpload,
makeAuthenticatedRequest,
} from "@/lib/autogpt-server-api/helpers";
@@ -97,6 +98,16 @@ function createResponse(
function createErrorResponse(error: unknown): NextResponse {
console.error("API proxy error:", error);
// If it's our custom ApiError, preserve the original status and response
if (error instanceof ApiError) {
return NextResponse.json(
error.response || { error: error.message, detail: error.message },
{ status: error.status },
);
}
// For other errors, use generic response
const detail =
error instanceof Error ? error.message : "An unknown error occurred";
return NextResponse.json(

View File

@@ -45,6 +45,7 @@ export function useOnboarding(step?: number, completeStep?: OnboardingStep) {
if (
!completeStep ||
!context.state ||
!context.state.completedSteps ||
context.state.completedSteps.includes(completeStep)
)
return;
@@ -79,22 +80,32 @@ export default function OnboardingProvider({
useEffect(() => {
const fetchOnboarding = async () => {
const enabled = await api.isOnboardingEnabled();
if (!enabled && pathname.startsWith("/onboarding")) {
router.push("/marketplace");
return;
}
const onboarding = await api.getUserOnboarding();
setState((prev) => ({ ...onboarding, ...prev }));
try {
const enabled = await api.isOnboardingEnabled();
if (!enabled && pathname.startsWith("/onboarding")) {
router.push("/marketplace");
return;
}
const onboarding = await api.getUserOnboarding();
// Redirect outside onboarding if completed
// If user did CONGRATS step, that means they completed introductory onboarding
if (
onboarding.completedSteps.includes("CONGRATS") &&
pathname.startsWith("/onboarding") &&
!pathname.startsWith("/onboarding/reset")
) {
router.push("/marketplace");
// Only update state if onboarding data is valid
if (onboarding) {
setState((prev) => ({ ...onboarding, ...prev }));
// Redirect outside onboarding if completed
// If user did CONGRATS step, that means they completed introductory onboarding
if (
onboarding.completedSteps &&
onboarding.completedSteps.includes("CONGRATS") &&
pathname.startsWith("/onboarding") &&
!pathname.startsWith("/onboarding/reset")
) {
router.push("/marketplace");
}
}
} catch (error) {
console.error("Failed to fetch onboarding data:", error);
// Don't update state on error to prevent null access issues
}
};
if (isUserLoading || !user) {
@@ -138,7 +149,12 @@ export default function OnboardingProvider({
const completeStep = useCallback(
(step: OnboardingStep) => {
if (!state || state.completedSteps.includes(step)) return;
if (
!state ||
!state.completedSteps ||
state.completedSteps.includes(step)
)
return;
updateState({
completedSteps: [...state.completedSteps, step],
@@ -148,7 +164,12 @@ export default function OnboardingProvider({
);
const incrementRuns = useCallback(() => {
if (!state || state.completedSteps.includes("RUN_AGENTS")) return;
if (
!state ||
!state.completedSteps ||
state.completedSteps.includes("RUN_AGENTS")
)
return;
const finished = state.agentRuns + 1 >= 10;
setNpsDialogOpen(finished);

View File

@@ -1,5 +1,17 @@
import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase";
export class ApiError extends Error {
public status: number;
public response?: any;
constructor(message: string, status: number, response?: any) {
super(message);
this.name = "ApiError";
this.status = status;
this.response = response;
}
}
export function buildRequestUrl(
baseUrl: string,
path: string,
@@ -172,6 +184,17 @@ export async function makeAuthenticatedRequest(
if (!response.ok) {
const errorDetail = await parseApiError(response);
// Try to parse the full response body for better error context
let responseData = null;
try {
const responseText = await response.clone().text();
if (responseText) {
responseData = JSON.parse(responseText);
}
} catch {
// Ignore parsing errors
}
// Handle authentication errors gracefully during logout
if (isAuthenticationError(response, errorDetail)) {
if (isLogoutInProgress()) {
@@ -189,8 +212,8 @@ export async function makeAuthenticatedRequest(
return null;
}
// For other errors, throw as normal
throw new Error(errorDetail);
// For other errors, throw ApiError with proper status code
throw new ApiError(errorDetail, response.status, responseData);
}
return parseApiResponse(response);
@@ -218,6 +241,17 @@ export async function makeAuthenticatedFileUpload(
// Handle authentication errors gracefully for file uploads too
const errorMessage = `Error uploading file: ${response.statusText}`;
// Try to parse error response
let responseData = null;
try {
const responseText = await response.clone().text();
if (responseText) {
responseData = JSON.parse(responseText);
}
} catch {
// Ignore parsing errors
}
if (response.status === 401 || response.status === 403) {
if (isLogoutInProgress()) {
console.debug(
@@ -229,7 +263,7 @@ export async function makeAuthenticatedFileUpload(
return "";
}
throw new Error(errorMessage);
throw new ApiError(errorMessage, response.status, responseData);
}
return await response.text();