diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 8c4c599..1dc4536 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -150,3 +150,4 @@ When working on this codebase, you might need to: - `/langchain-ai/langchainjs` for LangChain - `/langchain-ai/langgraph` for LangGraph - `/quantizor/markdown-to-jsx` for Markdown to JSX conversion + - `/context7/headlessui_com` for Headless UI components diff --git a/src/app/api/chat/route.ts b/src/app/api/chat/route.ts index d65a7a7..b82f0b3 100644 --- a/src/app/api/chat/route.ts +++ b/src/app/api/chat/route.ts @@ -56,6 +56,11 @@ type Body = { type ModelStats = { modelName: string; responseTime?: number; + usage?: { + input_tokens: number; + output_tokens: number; + total_tokens: number; + }; }; const handleEmitterEvents = async ( diff --git a/src/components/ChatWindow.tsx b/src/components/ChatWindow.tsx index 6184811..f0a3273 100644 --- a/src/components/ChatWindow.tsx +++ b/src/components/ChatWindow.tsx @@ -16,6 +16,11 @@ import NextError from 'next/error'; export type ModelStats = { modelName: string; responseTime?: number; + usage?: { + input_tokens: number; + output_tokens: number; + total_tokens: number; + }; }; export type AgentActionEvent = { diff --git a/src/components/CitationLink.tsx b/src/components/CitationLink.tsx new file mode 100644 index 0000000..3428acb --- /dev/null +++ b/src/components/CitationLink.tsx @@ -0,0 +1,55 @@ +import { Document } from '@langchain/core/documents'; +import { useState } from 'react'; +import MessageSource from './MessageSource'; + +interface CitationLinkProps { + number: string; + source?: Document; + url?: string; +} + +const CitationLink = ({ number, source, url }: CitationLinkProps) => { + const [showTooltip, setShowTooltip] = useState(false); + const linkContent = ( + + {number} + + ); + + // If we have source data, wrap with tooltip + if (source) { + return ( +
+ {source.metadata.url.replace(/.+\/\/|www.|\..+/g, '')} +
+ + {/* Preview content */} ++ {/* Use snippet for preview-only content, otherwise use pageContent */} + {source.metadata.processingType === 'preview-only' && + source.metadata.snippet + ? source.metadata.snippet + : source.pageContent?.length > 250 + ? source.pageContent.slice(0, 250) + '...' + : source.pageContent || 'No preview available'} +
+