( filePath: string, )
| 992 | * head (caller falls through to the full read — safe default). |
| 993 | */ |
| 994 | export async function readSessionStartDate( |
| 995 | filePath: string, |
| 996 | ): Promise<string | null> { |
| 997 | try { |
| 998 | const fd = await open(filePath, 'r') |
| 999 | try { |
| 1000 | const buf = Buffer.allocUnsafe(4096) |
| 1001 | const { bytesRead } = await fd.read(buf, 0, buf.length, 0) |
| 1002 | if (bytesRead === 0) return null |
| 1003 | const head = buf.toString('utf8', 0, bytesRead) |
| 1004 | |
| 1005 | // Only trust complete lines — the 4KB boundary may bisect a JSON entry. |
| 1006 | const lastNewline = head.lastIndexOf('\n') |
| 1007 | if (lastNewline < 0) return null |
| 1008 | |
| 1009 | for (const line of head.slice(0, lastNewline).split('\n')) { |
| 1010 | if (!line) continue |
| 1011 | let entry: { |
| 1012 | type?: unknown |
| 1013 | timestamp?: unknown |
| 1014 | isSidechain?: unknown |
| 1015 | } |
| 1016 | try { |
| 1017 | entry = jsonParse(line) |
| 1018 | } catch { |
| 1019 | continue |
| 1020 | } |
| 1021 | if (typeof entry.type !== 'string') continue |
| 1022 | if (!TRANSCRIPT_MESSAGE_TYPES.has(entry.type)) continue |
| 1023 | if (entry.isSidechain === true) continue |
| 1024 | if (typeof entry.timestamp !== 'string') return null |
| 1025 | const date = new Date(entry.timestamp) |
| 1026 | if (Number.isNaN(date.getTime())) return null |
| 1027 | return toDateString(date) |
| 1028 | } |
| 1029 | return null |
| 1030 | } finally { |
| 1031 | await fd.close() |
| 1032 | } |
| 1033 | } catch { |
| 1034 | return null |
| 1035 | } |
| 1036 | } |
| 1037 | |
| 1038 | function getEmptyStats(): ClaudeCodeStats { |
| 1039 | return { |
no test coverage detected