From 26da5c953f6ffd0c9ae92df7180730c9d7a53aac Mon Sep 17 00:00:00 2001 From: kartik Date: Mon, 24 Aug 2026 08:16:47 +0530 Subject: [PATCH 1/2] skip diagram analysis API call and show placeholder text instead --- frontend/app/analyze/[id]/page.tsx | 32 +++++++---------------------- frontend/app/search/[bmid]/page.tsx | 30 +++++++-------------------- 2 files changed, 14 insertions(+), 48 deletions(-) diff --git a/frontend/app/analyze/[id]/page.tsx b/frontend/app/analyze/[id]/page.tsx index f5c1c78..4bf4a9f 100644 --- a/frontend/app/analyze/[id]/page.tsx +++ b/frontend/app/analyze/[id]/page.tsx @@ -65,7 +65,6 @@ export default function AnalysisResultsPage({ const [results, setResults] = useState(null); const [isAnalysisLoading, setIsAnalysisLoading] = useState(!conversationId); const [diagramAnalysis, setDiagramAnalysis] = useState(""); - const [analysisError, setAnalysisError] = useState(""); const [combinedMessages, setCombinedMessages] = useState([]); const [biomodelData, setBiomodelData] = useState(null); const [biomodelLoading, setBiomodelLoading] = useState(true); @@ -135,32 +134,15 @@ export default function AnalysisResultsPage({ // is already part of the stored history, no need to regenerate it. if (conversationId) return; + // Diagram analyses are being precomputed and stored for all biomodels + // instead of generated on demand per request, so skip the /diagram + // call for now and show a placeholder instead. const fetchDiagramAnalysis = async () => { setIsAnalysisLoading(true); - setAnalysisError(""); - try { - const token = await getAccessToken(); - const apiUrl = process.env.NEXT_PUBLIC_API_URL; - const res = await fetch(`${apiUrl}/analyse/${id}/diagram`, { - method: "POST", - headers: { - Authorization: `Bearer ${token}`, - "Content-Type": "application/json", - }, - }); - - if (res.ok) { - const data = await res.json(); - setDiagramAnalysis(data.response || ""); - } else { - const errorData = await res.json(); - setAnalysisError(errorData.detail || "Failed to analyze diagram."); - } - } catch (err) { - setAnalysisError("Failed to fetch diagram analysis."); - } finally { - setIsAnalysisLoading(false); - } + setDiagramAnalysis( + "AI generated summary/analysis of this biomodel will be displayed here.", + ); + setIsAnalysisLoading(false); }; const fetchAnalysis = async () => { diff --git a/frontend/app/search/[bmid]/page.tsx b/frontend/app/search/[bmid]/page.tsx index f15c13b..3cd916b 100644 --- a/frontend/app/search/[bmid]/page.tsx +++ b/frontend/app/search/[bmid]/page.tsx @@ -29,7 +29,7 @@ import { Briefcase, Cog, } from "lucide-react"; -import { getAccessToken, useUser } from "@auth0/nextjs-auth0/client"; +import { useUser } from "@auth0/nextjs-auth0/client"; import { LoginRequiredDialog } from "@/components/login-required-dialog"; import { SignInOutButton } from "@/components/sign-in-out-button"; import { getOptionalAccessToken } from "@/lib/get-optional-access-token"; @@ -98,7 +98,6 @@ export default function BiomodelDetailPage() { conversationId ? "analysis" : "overview", ); const [diagramAnalysis, setDiagramAnalysis] = useState(""); - const [analysisError, setAnalysisError] = useState(""); const [combinedMessages, setCombinedMessages] = useState([]); const [showLoginDialog, setShowLoginDialog] = useState(false); const [diagramImageUrl, setDiagramImageUrl] = useState(""); @@ -205,28 +204,13 @@ export default function BiomodelDetailPage() { if (diagramFetchTriggeredRef.current) return; diagramFetchTriggeredRef.current = true; + // Diagram analyses are being precomputed and stored for all biomodels + // instead of generated on demand per request, so skip the /diagram + // call for now and show a placeholder instead. const fetchDiagramAnalysis = async () => { - try { - const token = await getAccessToken(); - const apiUrl = process.env.NEXT_PUBLIC_API_URL; - const res = await fetch(`${apiUrl}/analyse/${data.bmKey}/diagram`, { - method: "POST", - headers: { - Authorization: `Bearer ${token}`, - "Content-Type": "application/json", - }, - }); - - if (res.ok) { - const responseData = await res.json(); - setDiagramAnalysis(responseData.response || ""); - } else { - const errorData = await res.json(); - setAnalysisError(errorData.detail || "Failed to analyze diagram."); - } - } catch (err) { - setAnalysisError("Failed to fetch diagram analysis."); - } + setDiagramAnalysis( + "AI generated summary/analysis of this biomodel will be displayed here.", + ); }; fetchDiagramAnalysis(); From ccb1098d370cd55c68f5dda45a5c67873e5686c8 Mon Sep 17 00:00:00 2001 From: kartik Date: Mon, 24 Aug 2026 08:17:04 +0530 Subject: [PATCH 2/2] show user's query in analyze chat before the AI response --- frontend/app/analyze/[id]/page.tsx | 26 +++++++++++++++++--------- frontend/components/ChatBox.tsx | 17 ++++++++--------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/frontend/app/analyze/[id]/page.tsx b/frontend/app/analyze/[id]/page.tsx index 4bf4a9f..d177d35 100644 --- a/frontend/app/analyze/[id]/page.tsx +++ b/frontend/app/analyze/[id]/page.tsx @@ -65,7 +65,9 @@ export default function AnalysisResultsPage({ const [results, setResults] = useState(null); const [isAnalysisLoading, setIsAnalysisLoading] = useState(!conversationId); const [diagramAnalysis, setDiagramAnalysis] = useState(""); - const [combinedMessages, setCombinedMessages] = useState([]); + const [combinedMessages, setCombinedMessages] = useState< + { role: "user" | "assistant"; content: string }[] + >([]); const [biomodelData, setBiomodelData] = useState(null); const [biomodelLoading, setBiomodelLoading] = useState(true); const [showLoginDialog, setShowLoginDialog] = useState(false); @@ -188,21 +190,27 @@ export default function AnalysisResultsPage({ // Create combined messages when analyses are ready useEffect(() => { if (diagramAnalysis || results?.aiAnalysis) { - const messageParts: string[] = []; + const newMessages: { role: "user" | "assistant"; content: string }[] = []; if (diagramAnalysis) { - const diagramMessage = `# Diagram Analysis \n ${diagramAnalysis}`; - messageParts.push(diagramMessage); + newMessages.push({ + role: "assistant", + content: `# Diagram Analysis \n ${diagramAnalysis}`, + }); } - if (results?.aiAnalysis) { - const aiMessage = `# Biomodel Analysis \n ${results.aiAnalysis}`; - messageParts.push(aiMessage); + if (prompt.trim()) { + newMessages.push({ role: "user", content: prompt }); } - const joined_messages = messageParts.join("\n\n"); + if (results?.aiAnalysis) { + newMessages.push({ + role: "assistant", + content: `# Biomodel Analysis \n ${results.aiAnalysis}`, + }); + } - setCombinedMessages([joined_messages]); + setCombinedMessages(newMessages); } }, [diagramAnalysis, results?.aiAnalysis, id]); diff --git a/frontend/components/ChatBox.tsx b/frontend/components/ChatBox.tsx index 013c378..c452993 100644 --- a/frontend/components/ChatBox.tsx +++ b/frontend/components/ChatBox.tsx @@ -46,8 +46,10 @@ interface ChatParameters { llmMode: string; } +type SeedMessage = string | { role: "user" | "assistant"; content: string }; + interface ChatBoxProps { - startMessage: string | string[]; + startMessage: string | SeedMessage[]; quickActions: QuickAction[]; supplementalActions?: QuickAction[]; cardTitle: string; @@ -61,12 +63,12 @@ interface ChatBoxProps { } // Pure helpers — no dependency on component state/props. -const createInitialMessages = (startMsg: string | string[]): Message[] => { +const createInitialMessages = (startMsg: string | SeedMessage[]): Message[] => { if (Array.isArray(startMsg)) { - return startMsg.map((content, index) => ({ + return startMsg.map((seed, index) => ({ id: (index + 1).toString(), - role: "assistant" as const, - content, + role: typeof seed === "string" ? ("assistant" as const) : seed.role, + content: typeof seed === "string" ? seed : seed.content, timestamp: new Date(), })); } else if (startMsg) { @@ -166,10 +168,7 @@ export const ChatBox: React.FC = ({ useEffect(() => { if (boundConversationId) return; if (!startMessage || isInitialLoading) return; - setLocalSeedMessages((prev) => { - if (prev.some((m) => m.role === "user")) return prev; - return createInitialMessages(startMessage); - }); + setLocalSeedMessages(createInitialMessages(startMessage)); }, [startMessage, isInitialLoading, boundConversationId]); const handleQuickAction = (action: QuickAction) => {