diff --git a/packages/extension-core/src/extension/session-manager.ts b/packages/extension-core/src/extension/session-manager.ts index 9d51a7c..da3b6bf 100644 --- a/packages/extension-core/src/extension/session-manager.ts +++ b/packages/extension-core/src/extension/session-manager.ts @@ -186,9 +186,15 @@ export class SessionManager { * Get all sessions for a specific workflow file */ getSessionsForWorkflow(workflowFile: string): SessionData[] { + // Most recent first; between equal times (created or restored in the same + // millisecond), the one added later. return Array.from(this.sessions.values()) - .filter((s) => s.workflowFile === workflowFile) - .sort((a, b) => b.updatedAt - a.updatedAt); + .map((session, order) => ({ session, order })) + .filter(({ session }) => session.workflowFile === workflowFile) + .sort((a, b) => b.session.updatedAt - a.session.updatedAt + || b.session.createdAt - a.session.createdAt + || b.order - a.order) + .map(({ session }) => session); } /** diff --git a/packages/extension-core/test/session-manager.test.ts b/packages/extension-core/test/session-manager.test.ts index 8ee541b..7f4de88 100644 --- a/packages/extension-core/test/session-manager.test.ts +++ b/packages/extension-core/test/session-manager.test.ts @@ -247,17 +247,40 @@ describe('SessionManager', () => { describe('getSessionsForWorkflow', () => { it('should return sessions for specific workflow', async () => { - await sessionManager.createSession('/test/workflow1.py', 'Session 1'); - mockACPClient.createSession.mockResolvedValue('session-2'); - await sessionManager.createSession('/test/workflow2.py', 'Session 2'); - mockACPClient.createSession.mockResolvedValue('session-3'); - await sessionManager.createSession('/test/workflow1.py', 'Session 3'); + // Each session at its own time, so the order is the updatedAt sort's. + vi.useFakeTimers({ toFake: ['Date'] }); + try { + vi.setSystemTime(1_000); + await sessionManager.createSession('/test/workflow1.py', 'Session 1'); + vi.setSystemTime(2_000); + mockACPClient.createSession.mockResolvedValue('session-2'); + await sessionManager.createSession('/test/workflow2.py', 'Session 2'); + vi.setSystemTime(3_000); + mockACPClient.createSession.mockResolvedValue('session-3'); + await sessionManager.createSession('/test/workflow1.py', 'Session 3'); + } finally { + vi.useRealTimers(); + } const sessions = sessionManager.getSessionsForWorkflow('/test/workflow1.py'); expect(sessions).toHaveLength(2); // Sessions are sorted by updatedAt descending (most recent first) - expect(sessions.map((s) => s.name)).toEqual(['Session 1', 'Session 3']); + expect(sessions.map((s) => s.name)).toEqual(['Session 3', 'Session 1']); + }); + + it('should put the later of two sessions with the same time first', async () => { + vi.useFakeTimers({ toFake: ['Date'] }); + try { + vi.setSystemTime(5_000); + await sessionManager.createSession('/test/same.py', 'Earlier'); + mockACPClient.createSession.mockResolvedValue('session-later'); + await sessionManager.createSession('/test/same.py', 'Later'); + } finally { + vi.useRealTimers(); + } + + expect(sessionManager.getSessionsForWorkflow('/test/same.py').map((s) => s.name)).toEqual(['Later', 'Earlier']); }); it('should return empty array for workflow with no sessions', () => {