File size: 2,526 Bytes
ff0e173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
'use client';

import * as React from 'react';
import { ChatMessage } from '@/lib/kb-data';

/**
 * Shared chat session logic (messages + RAG request handling).
 *
 * Extracted so the same conversation engine drives both the dedicated
 * `/chat` page and the inline chat on the homepage (`/`).
 */
export function useChatSession() {
  const [messages, setMessages] = React.useState<ChatMessage[]>([]);
  const [isTyping, setIsTyping] = React.useState(false);

  // Monotonic counter guarantees unique keys even within the same millisecond.
  const idCounter = React.useRef(0);
  const makeId = React.useCallback(
    (role: 'user' | 'ai') => `m-${Date.now()}-${idCounter.current++}-${role}`,
    []
  );

  const sendMessage = React.useCallback(
    async (textToSend: string) => {
      if (!textToSend.trim()) return;

      const userMsg: ChatMessage = {
        id: makeId('user'),
        sender: 'user',
        text: textToSend,
        timestamp: new Date().toLocaleTimeString(),
      };

      setMessages((prev) => [...prev, userMsg]);
      setIsTyping(true);

      // Query the RAG pipeline: retrieve + rerank + grounded answer with citations.
      try {
        const res = await fetch('/api/chat', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ query: textToSend }),
        });

        if (!res.ok) {
          const err = await res.json().catch(() => ({}));
          throw new Error(err.error || `Request failed (${res.status})`);
        }

        const data: { text: string; sources?: Array<{ name: string; type: string }> } =
          await res.json();

        const aiMsg: ChatMessage = {
          id: makeId('ai'),
          sender: 'ai',
          text: data.text,
          timestamp: new Date().toLocaleTimeString(),
          sources: data.sources,
        };

        setMessages((prev) => [...prev, aiMsg]);
      } catch {
        const aiMsg: ChatMessage = {
          id: makeId('ai'),
          sender: 'ai',
          text:
            "Sorry — I ran into a problem reaching the knowledge base. Please make sure your Cohere API key is configured and try again.",
          timestamp: new Date().toLocaleTimeString(),
        };
        setMessages((prev) => [...prev, aiMsg]);
      } finally {
        setIsTyping(false);
      }
    },
    [makeId]
  );

  const reset = React.useCallback(() => {
    setMessages([]);
    setIsTyping(false);
  }, []);

  return { messages, isTyping, sendMessage, reset };
}