summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/hooks/useHistoryManager.ts
blob: baf9f7c5c0c28932e88479c5c132ff93ab89a38c (plain)
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
/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import { useState, useRef, useCallback } from 'react';
import { HistoryItem } from '../types.js';

export interface UseHistoryManagerReturn {
  history: HistoryItem[];
  addItemToHistory: (
    itemData: Omit<HistoryItem, 'id'>,
    baseTimestamp: number,
  ) => number; // Return the ID of the added item
  updateHistoryItem: (
    id: number,
    updates: Partial<Omit<HistoryItem, 'id'>>,
  ) => void;
  clearHistory: () => void;
}

/**
 * Custom hook to manage the chat history state.
 *
 * Encapsulates the history array, message ID generation, adding items,
 * updating items, and clearing the history.
 */
export function useHistoryManager(): UseHistoryManagerReturn {
  const [history, setHistory] = useState<HistoryItem[]>([]);
  const messageIdCounterRef = useRef(0);

  // Generates a unique message ID based on a timestamp and a counter.
  const getNextMessageId = useCallback((baseTimestamp: number): number => {
    // Increment *before* adding to ensure uniqueness against the base timestamp
    messageIdCounterRef.current += 1;
    return baseTimestamp + messageIdCounterRef.current;
  }, []);

  // Adds a new item to the history state with a unique ID and returns the ID.
  const addItemToHistory = useCallback(
    (itemData: Omit<HistoryItem, 'id'>, baseTimestamp: number): number => {
      const id = getNextMessageId(baseTimestamp);
      const newItem: HistoryItem = { ...itemData, id } as HistoryItem;
      setHistory((prevHistory) => [...prevHistory, newItem]);
      return id; // Return the generated ID
    },
    [getNextMessageId],
  );

  // Updates an existing history item identified by its ID.
  const updateHistoryItem = useCallback(
    (id: number, updates: Partial<Omit<HistoryItem, 'id'>>) => {
      setHistory((prevHistory) =>
        prevHistory.map((item) =>
          item.id === id ? ({ ...item, ...updates } as HistoryItem) : item,
        ),
      );
    },
    [],
  );

  // Clears the entire history state.
  const clearHistory = useCallback(() => {
    setHistory([]);
    messageIdCounterRef.current = 0; // Reset counter when history is cleared
  }, []);

  return { history, addItemToHistory, updateHistoryItem, clearHistory };
}