don't ingest onboarding doc for now

This commit is contained in:
phact 2025-10-24 04:12:14 -04:00
parent e3353bb0f8
commit de413c880a
5 changed files with 116 additions and 33 deletions

View file

@ -29,6 +29,87 @@ export async function duplicateCheck(
return response.json(); return response.json();
} }
export async function uploadFileForContext(
file: File
): Promise<UploadFileResult> {
window.dispatchEvent(
new CustomEvent("fileUploadStart", {
detail: { filename: file.name },
})
);
try {
const formData = new FormData();
formData.append("file", file);
const uploadResponse = await fetch("/api/upload_context", {
method: "POST",
body: formData,
});
let payload: unknown;
try {
payload = await uploadResponse.json();
} catch (error) {
throw new Error("Upload failed: unable to parse server response");
}
const uploadJson =
typeof payload === "object" && payload !== null ? payload : {};
if (!uploadResponse.ok) {
const errorMessage =
(uploadJson as { error?: string }).error ||
"Upload failed";
throw new Error(errorMessage);
}
const fileId =
(uploadJson as { response_id?: string }).response_id || "uploaded";
const filePath =
(uploadJson as { filename?: string }).filename || file.name;
const result: UploadFileResult = {
fileId,
filePath,
run: null,
deletion: null,
unified: false,
raw: uploadJson,
};
window.dispatchEvent(
new CustomEvent("fileUploaded", {
detail: {
file,
result: {
file_id: fileId,
file_path: filePath,
run: null,
deletion: null,
unified: false,
},
},
})
);
return result;
} catch (error) {
window.dispatchEvent(
new CustomEvent("fileUploadError", {
detail: {
filename: file.name,
error:
error instanceof Error ? error.message : "Upload failed",
},
})
);
throw error;
} finally {
window.dispatchEvent(new CustomEvent("fileUploadComplete"));
}
}
export async function uploadFile( export async function uploadFile(
file: File, file: File,
replace = false replace = false

View file

@ -698,9 +698,24 @@ function ChatPage() {
}, [endpoint, setPreviousResponseIds, setLoading]); }, [endpoint, setPreviousResponseIds, setLoading]);
// Check if onboarding is complete by looking at local storage // Check if onboarding is complete by looking at local storage
const isOnboardingComplete = const [isOnboardingComplete, setIsOnboardingComplete] = useState(() => {
typeof window !== "undefined" && if (typeof window === "undefined") return false;
localStorage.getItem("onboarding-step") === null; return localStorage.getItem("onboarding-step") === null;
});
// Listen for storage changes to detect when onboarding completes
useEffect(() => {
const checkOnboarding = () => {
if (typeof window !== "undefined") {
setIsOnboardingComplete(localStorage.getItem("onboarding-step") === null);
}
};
// Check periodically since storage events don't fire in the same tab
const interval = setInterval(checkOnboarding, 500);
return () => clearInterval(interval);
}, []);
const { data: nudges = [], cancel: cancelNudges } = useGetNudgesQuery( const { data: nudges = [], cancel: cancelNudges } = useGetNudgesQuery(
previousResponseIds[endpoint], previousResponseIds[endpoint],

View file

@ -26,6 +26,7 @@ export function OnboardingContent({
); );
const [isLoadingModels, setIsLoadingModels] = useState<boolean>(false); const [isLoadingModels, setIsLoadingModels] = useState<boolean>(false);
const [loadingStatus, setLoadingStatus] = useState<string[]>([]); const [loadingStatus, setLoadingStatus] = useState<string[]>([]);
const [hasStartedOnboarding, setHasStartedOnboarding] = useState<boolean>(false);
const { streamingMessage, isLoading, sendMessage } = useChatStreaming({ const { streamingMessage, isLoading, sendMessage } = useChatStreaming({
onComplete: (message, newResponseId) => { onComplete: (message, newResponseId) => {
@ -83,10 +84,13 @@ export function OnboardingContent({
text="Let's get started by setting up your model provider." text="Let's get started by setting up your model provider."
isLoadingModels={isLoadingModels} isLoadingModels={isLoadingModels}
loadingStatus={loadingStatus} loadingStatus={loadingStatus}
reserveSpaceForThinking={true} reserveSpaceForThinking={!hasStartedOnboarding}
> >
<OnboardingCard <OnboardingCard
onComplete={handleStepComplete} onComplete={() => {
setHasStartedOnboarding(true);
handleStepComplete();
}}
setIsLoadingModels={setIsLoadingModels} setIsLoadingModels={setIsLoadingModels}
setLoadingStatus={setLoadingStatus} setLoadingStatus={setLoadingStatus}
/> />

View file

@ -153,10 +153,10 @@ export function OnboardingStep({
)} )}
chatMessage={text} chatMessage={text}
/> />
) : reserveSpaceForThinking && !isCompleted ? ( ) : (
<div className="flex flex-col gap-2 py-1.5"> <>
<p <p
className={`text-foreground text-sm transition-colors duration-300 ${ className={`text-foreground text-sm py-1.5 transition-colors duration-300 ${
isCompleted ? "text-placeholder-foreground" : "" isCompleted ? "text-placeholder-foreground" : ""
}`} }`}
> >
@ -165,19 +165,10 @@ export function OnboardingStep({
<span className="inline-block w-1 h-3.5 bg-primary ml-1 animate-pulse" /> <span className="inline-block w-1 h-3.5 bg-primary ml-1 animate-pulse" />
)} )}
</p> </p>
<div className="h-6" /> {reserveSpaceForThinking && (
</div> <div className="h-8" />
) : (
<p
className={`text-foreground text-sm py-1.5 transition-colors duration-300 ${
isCompleted ? "text-placeholder-foreground" : ""
}`}
>
{displayedText}
{!showChildren && !isCompleted && (
<span className="inline-block w-1 h-3.5 bg-primary ml-1 animate-pulse" />
)} )}
</p> </>
)} )}
{children && ( {children && (
<AnimatePresence> <AnimatePresence>

View file

@ -1,6 +1,6 @@
import { ChangeEvent, useRef, useState } from "react"; import { ChangeEvent, useRef, useState } from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { duplicateCheck, uploadFile } from "@/lib/upload-utils"; import { uploadFileForContext } from "@/lib/upload-utils";
import { AnimatePresence, motion } from "motion/react"; import { AnimatePresence, motion } from "motion/react";
import { AnimatedProviderSteps } from "@/app/onboarding/components/animated-provider-steps"; import { AnimatedProviderSteps } from "@/app/onboarding/components/animated-provider-steps";
@ -28,12 +28,11 @@ const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => {
fileInputRef.current?.click(); fileInputRef.current?.click();
}; };
const performUpload = async (file: File) => {
const performUpload = async (file: File, replace = false) => {
setIsUploading(true); setIsUploading(true);
try { try {
setCurrentStep(1); setCurrentStep(0);
await uploadFile(file, replace); await uploadFileForContext(file);
console.log("Document uploaded successfully"); console.log("Document uploaded successfully");
} catch (error) { } catch (error) {
console.error("Upload failed", (error as Error).message); console.error("Upload failed", (error as Error).message);
@ -54,14 +53,7 @@ const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => {
} }
try { try {
setCurrentStep(0); await performUpload(selectedFile);
const duplicateInfo = await duplicateCheck(selectedFile);
if (duplicateInfo.exists) {
console.log("Duplicate file detected");
return;
}
await performUpload(selectedFile, false);
} catch (error) { } catch (error) {
console.error("Unable to prepare file for upload", (error as Error).message); console.error("Unable to prepare file for upload", (error as Error).message);
} finally { } finally {