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

Method reAppendSessionMetadata

src/utils/sessionStorage.ts:721–839  ·  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

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