diff --git a/server/openai-codex.js b/server/openai-codex.js index ddc023f..d83d39b 100644 --- a/server/openai-codex.js +++ b/server/openai-codex.js @@ -280,7 +280,8 @@ export async function queryCodex(command, options = {}, ws) { // Send completion event sendMessage(ws, { type: 'codex-complete', - sessionId: currentSessionId + sessionId: currentSessionId, + actualSessionId: thread.id }); } catch (error) { diff --git a/server/projects.js b/server/projects.js index a4efb10..ff7a8d1 100755 --- a/server/projects.js +++ b/server/projects.js @@ -1206,7 +1206,12 @@ async function getCodexSessions(projectPath) { const sessionData = await parseCodexSessionFile(filePath); // Check if this session matches the project path - if (sessionData && sessionData.cwd === projectPath) { + // Handle Windows long paths with \\?\ prefix + const sessionCwd = sessionData?.cwd || ''; + const cleanSessionCwd = sessionCwd.startsWith('\\\\?\\') ? sessionCwd.slice(4) : sessionCwd; + const cleanProjectPath = projectPath.startsWith('\\\\?\\') ? projectPath.slice(4) : projectPath; + + if (sessionData && (sessionData.cwd === projectPath || cleanSessionCwd === cleanProjectPath || path.relative(cleanSessionCwd, cleanProjectPath) === '')) { sessions.push({ id: sessionData.id, summary: sessionData.summary || 'Codex Session', @@ -1273,12 +1278,12 @@ async function parseCodexSessionFile(filePath) { // Count messages and extract user messages for summary if (entry.type === 'event_msg' && entry.payload?.type === 'user_message') { messageCount++; - if (entry.payload.text) { - lastUserMessage = entry.payload.text; + if (entry.payload.message) { + lastUserMessage = entry.payload.message; } } - if (entry.type === 'response_item' && entry.payload?.type === 'message') { + if (entry.type === 'response_item' && entry.payload?.type === 'message' && entry.payload.role === 'assistant') { messageCount++; } diff --git a/src/components/ChatInterface.jsx b/src/components/ChatInterface.jsx index 337513c..5d86001 100644 --- a/src/components/ChatInterface.jsx +++ b/src/components/ChatInterface.jsx @@ -2971,6 +2971,9 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess if (latestMessage.sessionId && !currentSessionId) { sessionStorage.setItem('pendingSessionId', latestMessage.sessionId); + // Mark as system change to prevent clearing messages when session ID updates + setIsSystemSessionChange(true); + // Session Protection: Replace temporary "new-session-*" identifier with real session ID // This maintains protection continuity - no gap between temp ID and real ID // The temporary session is removed and real session is marked as active @@ -3530,8 +3533,13 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess } const codexPendingSessionId = sessionStorage.getItem('pendingSessionId'); + const codexActualSessionId = latestMessage.actualSessionId || codexPendingSessionId; if (codexPendingSessionId && !currentSessionId) { - setCurrentSessionId(codexPendingSessionId); + setCurrentSessionId(codexActualSessionId); + setIsSystemSessionChange(true); + if (onNavigateToSession) { + onNavigateToSession(codexActualSessionId); + } sessionStorage.removeItem('pendingSessionId'); console.log('Codex session complete, ID set to:', codexPendingSessionId); }