MCPcopy
hub / github.com/claude-code-best/claude-code / reAppendSessionMetadata

Method reAppendSessionMetadata

src/utils/sessionStorage.ts:735–861  ·  view source on GitHub ↗

* Re-append cached session metadata to the end of the transcript file. * This ensures metadata stays within the tail window that readLiteMetadata * reads during progressive loading. * * Called from two contexts with different file-ordering implications: * - During compaction (compact.

(skipTitleRefresh = false)

Source from the content-addressed store, hash-verified

733 * external-writer concern — their caches are authoritative.
734 */
735 reAppendSessionMetadata(skipTitleRefresh = false): void {
736 if (!this.sessionFile) return
737 const sessionId = getSessionId() as UUID
738 if (!sessionId) return
739
740 // One sync tail read to refresh SDK-mutable fields. Same
741 // LITE_READ_BUF_SIZE window readLiteMetadata uses. Empty string on
742 // failure → extract returns null → cache is the only source of truth.
743 const tail = readFileTailSync(this.sessionFile)
744
745 // Absorb any fresher SDK-written title/tag into our cache. If the SDK
746 // wrote while we had the session open, our cache is stale — the tail
747 // value is authoritative. If the tail has nothing (evicted or never
748 // written externally), the cache stands.
749 //
750 // Filter with startsWith to match only top-level JSONL entries (col 0)
751 // and not "type":"tag" appearing inside a nested tool_use input that
752 // happens to be JSON-serialized into a message.
753 const tailLines = tail.split('\n')
754 if (!skipTitleRefresh) {
755 const titleLine = tailLines.findLast(l =>
756 l.startsWith('{"type":"custom-title"'),
757 )
758 if (titleLine) {
759 const tailTitle = extractLastJsonStringField(titleLine, 'customTitle')
760 // `!== undefined` distinguishes no-match from empty-string match.
761 // renameSession rejects empty titles, but the CLI is defensive: an
762 // external writer with customTitle:"" should clear the cache so the
763 // re-append below skips it (instead of resurrecting a stale title).
764 if (tailTitle !== undefined) {
765 this.currentSessionTitle = tailTitle || undefined
766 }
767 }
768 }
769 const tagLine = tailLines.findLast(l => l.startsWith('{"type":"tag"'))
770 if (tagLine) {
771 const tailTag = extractLastJsonStringField(tagLine, 'tag')
772 // Same: tagSession(id, null) writes `tag:""` to clear.
773 if (tailTag !== undefined) {
774 this.currentSessionTag = tailTag || undefined
775 }
776 }
777
778 // lastPrompt is re-appended so readLiteMetadata can show what the
779 // user was most recently doing. Written first so customTitle/tag/etc
780 // land closer to EOF (they're the more critical fields for tail reads).
781 if (this.currentSessionLastPrompt) {
782 appendEntryToFile(this.sessionFile, {
783 type: 'last-prompt',
784 lastPrompt: this.currentSessionLastPrompt,
785 sessionId,
786 })
787 }
788 // Unconditional: cache was refreshed from tail above; re-append keeps
789 // the entry at EOF so compaction-pushed content doesn't evict it.
790 if (this.currentSessionTitle) {
791 appendEntryToFile(this.sessionFile, {
792 type: 'custom-title',

Callers 4

getProjectFunction · 0.80
adoptResumedSessionFileFunction · 0.80
reAppendSessionMetadataFunction · 0.80

Calls 4

getSessionIdFunction · 0.85
readFileTailSyncFunction · 0.85
appendEntryToFileFunction · 0.85

Tested by

no test coverage detected