diff --git a/src/main/utils/jsonl.ts b/src/main/utils/jsonl.ts index f500da32..941fcb8b 100644 --- a/src/main/utils/jsonl.ts +++ b/src/main/utils/jsonl.ts @@ -551,6 +551,8 @@ export async function analyzeSessionFileMetadata( if ( !firstUserMessage && + // teammate relays (and system output/interruptions) must not become the preview + isParsedUserChunkMessage(parsed) && entry.type === 'user' && !('isMeta' in entry && entry.isMeta === true) ) { diff --git a/test/main/utils/jsonl.test.ts b/test/main/utils/jsonl.test.ts index a813ae29..f14af91a 100644 --- a/test/main/utils/jsonl.test.ts +++ b/test/main/utils/jsonl.test.ts @@ -452,6 +452,71 @@ describe('jsonl', () => { } }); + it('skips teammate relays when picking firstUserMessage', async () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsonl-relay-')); + try { + const filePath = path.join(tempDir, 'session.jsonl'); + const relay = + 'hello\nWhy is this tag in the log?'; + const lines = [ + JSON.stringify({ + type: 'user', + uuid: 'u1', + timestamp: '2026-01-01T00:00:00.000Z', + message: { role: 'user', content: relay }, + isMeta: false, + }), + ]; + fs.writeFileSync(filePath, `${lines.join('\n')}\n`, 'utf8'); + + const result = await analyzeSessionFileMetadata(filePath); + + expect(result.firstUserMessage).toBeNull(); + } finally { + try { + fs.rmSync(tempDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 }); + } catch { + // Best-effort cleanup; ignore ENOTEMPTY on Windows when dir is in use + } + } + }); + + it('picks a later real user message when the session opens with a relay', async () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsonl-relay2-')); + try { + const filePath = path.join(tempDir, 'session.jsonl'); + const relay = + 'hello\nWhy is this tag in the log?'; + const lines = [ + JSON.stringify({ + type: 'user', + uuid: 'u1', + timestamp: '2026-01-01T00:00:00.000Z', + message: { role: 'user', content: relay }, + isMeta: false, + }), + JSON.stringify({ + type: 'user', + uuid: 'u2', + timestamp: '2026-01-01T00:00:05.000Z', + message: { role: 'user', content: 'the actual user question' }, + isMeta: false, + }), + ]; + fs.writeFileSync(filePath, `${lines.join('\n')}\n`, 'utf8'); + + const result = await analyzeSessionFileMetadata(filePath); + + expect(result.firstUserMessage?.text).toBe('the actual user question'); + } finally { + try { + fs.rmSync(tempDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 }); + } catch { + // Best-effort cleanup; ignore ENOTEMPTY on Windows when dir is in use + } + } + }); + it('sums total spend across all assistant usage in one pass', async () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsonl-spend-')); try {