fix: apply session reset fix to SessionStore.createSDKSession (correct location)

Previous fix was applied to sessions/create.ts which is unused.
The actual method called by the worker is SessionStore.createSDKSession
in src/services/sqlite/SessionStore.ts.

Now resets started_at_epoch when session is completed or older than
the 4-hour wall-clock limit, preventing age limit blocks after mac
sleep/resume without proper SessionEnd.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
JOUNGWOOK KWON
2026-04-19 16:00:31 +09:00
parent e88e1a0ceb
commit daa937270c
+23 -2
View File
@@ -1626,10 +1626,31 @@ export class SessionStore {
// Session reuse: Return existing session ID if already created for this contentSessionId.
const existing = this.db.prepare(`
SELECT id, platform_source FROM sdk_sessions WHERE content_session_id = ?
`).get(contentSessionId) as { id: number; platform_source: string | null } | undefined;
SELECT id, platform_source, completed_at_epoch, started_at_epoch FROM sdk_sessions WHERE content_session_id = ?
`).get(contentSessionId) as { id: number; platform_source: string | null; completed_at_epoch: number | null; started_at_epoch: number } | undefined;
// 4-hour wall-clock limit (must match SDKAgent.MAX_SESSION_WALL_CLOCK_MS)
const MAX_SESSION_MS = 4 * 60 * 60 * 1000;
if (existing) {
// Reset session if completed OR older than the wall-clock age limit.
// Handles mac sleep/resume where worker restarts but SessionEnd never fired,
// leaving a stale started_at_epoch that blocks all observations and summaries.
const ageMs = nowEpoch - existing.started_at_epoch;
const needsReset = !!existing.completed_at_epoch || ageMs > MAX_SESSION_MS;
if (needsReset) {
logger.info('SESSION', 'Resetting stale session on resume (mac sleep/worker-restart detected)', {
contentSessionId,
ageHours: Math.round(ageMs / 36e5 * 10) / 10,
wasCompleted: !!existing.completed_at_epoch
});
this.db.prepare(`
UPDATE sdk_sessions
SET started_at_epoch = ?, started_at = ?, completed_at_epoch = NULL, completed_at = NULL, status = 'active'
WHERE content_session_id = ?
`).run(nowEpoch, now.toISOString(), contentSessionId);
}
// Backfill project if session was created by another hook with empty project
if (project) {
this.db.prepare(`