MCPcopy
hub / github.com/opactorai/Claudable / ChatLog

Function ChatLog

components/chat/ChatLog.tsx:1000–3055  ·  view source on GitHub ↗
({ projectId, onSessionStatusChange, onProjectStatusUpdate, onSseFallbackActive, startRequest, completeRequest, onAddUserMessage }: ChatLogProps)

Source from the content-addressed store, hash-verified

998}
999
1000export default function ChatLog({ projectId, onSessionStatusChange, onProjectStatusUpdate, onSseFallbackActive, startRequest, completeRequest, onAddUserMessage }: ChatLogProps) {
1001 const [messages, setMessages] = useState<ChatMessage[]>([]);
1002 const [logs, setLogs] = useState<LogEntry[]>([]);
1003 const [selectedLog, setSelectedLog] = useState<LogEntry | null>(null);
1004 const [isLoading, setIsLoading] = useState(true);
1005 const [hasLoadedOnce, setHasLoadedOnce] = useState(false);
1006 const [hasError, setHasError] = useState(false);
1007 const [errorMessage, setErrorMessage] = useState<string | null>(null);
1008 const [activeSession, setActiveSession] = useState<ActiveSession | null>(null);
1009 const [isWaitingForResponse, setIsWaitingForResponse] = useState(false);
1010 const [needsHistoryRefresh, setNeedsHistoryRefresh] = useState(false);
1011 const logsEndRef = useRef<HTMLDivElement>(null);
1012 const pollIntervalRef = useRef<NodeJS.Timeout | null>(null);
1013 const hasLoadedInitialDataRef = useRef(false);
1014 const sseFallbackTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
1015 const hasLoggedSseFallbackRef = useRef(false);
1016 const [enableSseFallback, setEnableSseFallback] = useState(false);
1017 const [isSseConnected, setIsSseConnected] = useState(false);
1018 const [failedImageUrls, setFailedImageUrls] = useState<Set<string>>(new Set());
1019 const [expandedToolMessages, setExpandedToolMessages] = useState<Record<string, ToolExpansionState>>({});
1020 const fallbackMessageIdRef = useRef<Map<string, string>>(new Map());
1021 const visibleToolMessageIdsRef = useRef<Set<string>>(new Set());
1022
1023 const ensureStableMessageId = useCallback((message: ChatMessage): string => {
1024 if (message.id) {
1025 return message.id;
1026 }
1027
1028 const parts: string[] = [];
1029 const addPart = (label: string, value: unknown) => {
1030 const candidate = pickFirstString(value);
1031 if (candidate) {
1032 parts.push(`${label}:${candidate}`);
1033 }
1034 };
1035
1036 addPart('request', message.requestId);
1037 addPart('parent', message.parentMessageId);
1038 addPart('session', message.sessionId);
1039 addPart('type', message.messageType);
1040 addPart('role', message.role);
1041 addPart('cli', message.cliSource);
1042 addPart('created', message.createdAt);
1043
1044 const metadata =
1045 message.metadata && typeof message.metadata === 'object'
1046 ? (message.metadata as Record<string, unknown>)
1047 : null;
1048 if (metadata) {
1049 const toolCallId = extractToolCallId(metadata);
1050 if (toolCallId) {
1051 addPart('tool_call', toolCallId);
1052 }
1053 }
1054
1055 const fingerprint =
1056 parts.length > 0
1057 ? parts.join('|')

Callers

nothing calls this directly

Calls 15

toChatMessageFunction · 0.90
normalizeChatContentFunction · 0.90
useWebSocketFunction · 0.90
toRelativePathFunction · 0.90
addPartFunction · 0.85
extractToolCallIdFunction · 0.85
randomMessageIdFunction · 0.85
integrateMessagesFunction · 0.85
connectSseFunction · 0.85
expandMessagesListFunction · 0.85

Tested by

no test coverage detected