MCPcopy Index your code
hub / github.com/codeaashu/claude-code / useLogMessages

Function useLogMessages

src/hooks/useLogMessages.ts:19–119  ·  view source on GitHub ↗
(messages: Message[], ignore: boolean = false)

Source from the content-addressed store, hash-verified

17 * @param ignore When true, messages will not be recorded to the transcript
18 */
19export function useLogMessages(messages: Message[], ignore: boolean = false) {
20 const teamContext = useAppState(s => s.teamContext)
21
22 // messages is append-only between compactions, so track where we left off
23 // and only pass the new tail to recordTranscript. Avoids O(n) filter+scan
24 // on every setMessages (~20x/turn, so n=3000 was ~120k wasted iterations).
25 const lastRecordedLengthRef = useRef(0)
26 const lastParentUuidRef = useRef<UUID | undefined>(undefined)
27 // First-uuid change = compaction or /clear rebuilt the array; length alone
28 // can't detect this since post-compact [CB,summary,...keep,new] may be longer.
29 const firstMessageUuidRef = useRef<UUID | undefined>(undefined)
30 // Guard against stale async .then() overwriting a fresher sync update when
31 // an incremental render fires before the compaction .then() resolves.
32 const callSeqRef = useRef(0)
33
34 useEffect(() => {
35 if (ignore) return
36
37 const currentFirstUuid = messages[0]?.uuid as UUID | undefined
38 const prevLength = lastRecordedLengthRef.current
39
40 // First-render: firstMessageUuidRef is undefined. Compaction: first uuid changes.
41 // Both are !isIncremental, but first-render sync-walk is safe (no messagesToKeep).
42 const wasFirstRender = firstMessageUuidRef.current === undefined
43 const isIncremental =
44 currentFirstUuid !== undefined &&
45 !wasFirstRender &&
46 currentFirstUuid === firstMessageUuidRef.current &&
47 prevLength <= messages.length
48 // Same-head shrink: tombstone filter, rewind, snip, partial-compact.
49 // Distinguished from compaction (first uuid changes) because the tail
50 // is either an existing on-disk message or a fresh message that this
51 // same effect's recordTranscript(fullArray) will write — see sync-walk
52 // guard below.
53 const isSameHeadShrink =
54 currentFirstUuid !== undefined &&
55 !wasFirstRender &&
56 currentFirstUuid === firstMessageUuidRef.current &&
57 prevLength > messages.length
58
59 const startIndex = isIncremental ? prevLength : 0
60 if (startIndex === messages.length) return
61
62 // Full array on first call + after compaction: recordTranscript's own
63 // O(n) dedup loop handles messagesToKeep interleaving correctly there.
64 const slice = startIndex === 0 ? messages : messages.slice(startIndex)
65 const parentHint = isIncremental ? lastParentUuidRef.current : undefined
66
67 // Fire and forget - we don't want to block the UI.
68 const seq = ++callSeqRef.current
69 void recordTranscript(
70 slice,
71 isAgentSwarmsEnabled()
72 ? {
73 teamName: teamContext?.teamName,
74 agentName: teamContext?.selfAgentName,
75 }
76 : {},

Callers 1

REPLFunction · 0.85

Calls 4

useAppStateFunction · 0.85
recordTranscriptFunction · 0.85
isAgentSwarmsEnabledFunction · 0.85
cleanMessagesForLoggingFunction · 0.85

Tested by

no test coverage detected