From 1c490ce2fa9413271ec98ae803db843ba92c1c06 Mon Sep 17 00:00:00 2001 From: Woody Date: Wed, 29 Apr 2026 09:54:40 +0800 Subject: [PATCH] fix: inline citations now upgrade to highlighted view (Phase 5.4) - Added sub_question_text to frontend SourceMetadata type - SubQuestionSection enriches sources with parent sub-question text - buildCitationUrl routes to highlight page when sub_question_text present - processCitations threads highlightReadyKeys through inline citations --- frontend/src/components/ResponsePanel.tsx | 7 +++++-- frontend/src/types/index.ts | 1 + frontend/src/utils/citationParser.ts | 25 ++++++++++++++++------- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/ResponsePanel.tsx b/frontend/src/components/ResponsePanel.tsx index 5a4c5da..4a726db 100644 --- a/frontend/src/components/ResponsePanel.tsx +++ b/frontend/src/components/ResponsePanel.tsx @@ -98,10 +98,13 @@ function SubQuestionSection({ highlightReadyKeys: Set }) { const [expanded, setExpanded] = useState(false) + // Enrich sources with sub_question_text so buildCitationUrl can route to highlight page. // Look up citations across ALL sub-questions' sources because the LLM // may cite chunks from other sub-questions' contexts. - const allSources = allSubQuestionSources.flatMap(sq => sq.sources) - const processedAnswer = processCitations(answerSection, allSources) + const allSources = allSubQuestionSources.flatMap(sq => + sq.sources.map(s => ({ ...s, sub_question_text: sq.sub_question_text })) + ) + const processedAnswer = processCitations(answerSection, allSources, highlightReadyKeys) return (
): string { const lookup = buildCitationLookupForSubq(subQuestionSources, subqIndex) - return replaceCitationPatterns(answerSection, lookup) + return replaceCitationPatterns(answerSection, lookup, highlightKeys) } -function buildCitationUrl(source: SourceMetadata): string | null { +function buildCitationUrl(source: SourceMetadata, highlightReady?: boolean): string | null { + if (highlightReady && source.document_id && source.sub_question_text) { + return `/api/v1/v2/highlights?document_id=${encodeURIComponent(source.document_id)}&chunk_index=${source.chunk_index}&sub_question=${encodeURIComponent(source.sub_question_text)}` + } if (source.chunk_file_path) { return getPdfViewerUrl( source.chunk_file_path, @@ -99,7 +103,8 @@ function findSource( function replaceCitationPatterns( text: string, - lookup: Map + lookup: Map, + highlightKeys?: Set ): string { const citationPattern = /(?): string { if (!sources.length) return text const lookup = buildCitationLookup(sources) - return replaceCitationPatterns(text, lookup) + return replaceCitationPatterns(text, lookup, highlightKeys) } export function extractCitedSources(answerText: string, sources: SourceMetadata[]): SourceMetadata[] {