@@ -349,7 +349,7 @@ function AIMessageContent({
ol: ({ children }) =>
{children}
,
}}
>
- {markdownWithLinks}
+ {markdownWithCompactRefs}
)
diff --git a/frontend/src/lib/utils/source-references.tsx b/frontend/src/lib/utils/source-references.tsx
index a76a645..26f013e 100644
--- a/frontend/src/lib/utils/source-references.tsx
+++ b/frontend/src/lib/utils/source-references.tsx
@@ -23,6 +23,12 @@ export interface ExtractedReferences {
references: ExtractedReference[]
}
+export interface ReferenceData {
+ number: number
+ type: ReferenceType
+ id: string
+}
+
/**
* Parse source references from text
*
@@ -307,6 +313,163 @@ export function createReferenceLinkComponent(
return ReferenceLinkComponent
}
+/**
+ * Convert references in text to compact numbered format with reference list
+ *
+ * This function transforms verbose inline references like [source:abc123] into
+ * compact numbered citations [1], [2], etc., and appends a "References:" section
+ * at the bottom of the message with the full reference details.
+ *
+ * Algorithm:
+ * 1. Parse all references using parseSourceReferences()
+ * 2. Build a reference map to deduplicate and assign numbers
+ * 3. Replace inline references with numbered citations
+ * 4. Append reference list at the bottom
+ *
+ * @param text - Original text with references
+ * @returns Text with numbered citations and reference list appended
+ *
+ * @example
+ * Input: "See [source:abc] and [note:xyz]. Also [source:abc] again."
+ * Output: "See [1] and [2]. Also [1] again.\n\nReferences:\n[1] - [source:abc]\n[2] - [note:xyz]"
+ */
+export function convertReferencesToCompactMarkdown(text: string): string {
+ // Step 1: Parse all references using existing function
+ const references = parseSourceReferences(text)
+
+ // Step 2: If no references found, return original text
+ if (references.length === 0) {
+ return text
+ }
+
+ // Step 3: Build reference map (deduplicate and assign numbers)
+ const referenceMap = new Map