Remove module-level SESSION_HISTORY Map from codex-mcp-agent.ts

Refactored history storage from module-level Map to instance-level
persistedHistory field. This fixes:
- Memory leak: sessions were never cleaned up from global Map
- Shared state: unrelated sessions could collide
- Restart handling: history now always loads from disk on resume

Changes:
- Removed SESSION_HISTORY Map (was at line 118)
- Constructor now sets historyPending=true for resume instead of
  looking up from global Map
- connect() always loads from disk when resuming
- recordHistory() appends to this.persistedHistory instead of Map
- flushPendingHistory() appends to this.persistedHistory instead of Map
- loadPersistedHistoryFromDisk() no longer populates global Map

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Mohamed Boudra
2025-12-25 19:26:28 +07:00
parent f22f76c56b
commit aea8a66112

View File

@@ -115,8 +115,6 @@ const MODE_PRESETS: Record<
},
};
const SESSION_HISTORY = new Map<string, AgentTimelineItem[]>();
function createToolCallTimelineItem(
data: Omit<ToolCallTimelineItem, "type">
): AgentTimelineItem {
@@ -2563,11 +2561,8 @@ class CodexMcpAgentSession implements AgentSession {
this.conversationId = this.sessionId;
}
}
// Try in-memory history first (for same-process resume)
const history = this.sessionId ? SESSION_HISTORY.get(this.sessionId) : undefined;
this.persistedHistory = history ? [...history] : [];
this.historyPending = this.persistedHistory.length > 0;
// Note: If SESSION_HISTORY is empty (daemon restarted), we load from disk in connect()
// Mark history as pending; actual loading happens in connect() from disk
this.historyPending = true;
}
this.client = new Client(
@@ -2608,9 +2603,8 @@ class CodexMcpAgentSession implements AgentSession {
async connect(): Promise<void> {
if (this.connected) return;
// If resuming with no in-memory history, load from rollout file on disk
// This handles the case where the daemon restarted and SESSION_HISTORY was lost
if (this.resumeHandle && this.sessionId && this.persistedHistory.length === 0) {
// Load history from disk when resuming a session
if (this.resumeHandle && this.sessionId) {
await this.loadPersistedHistoryFromDisk();
}
@@ -2641,8 +2635,6 @@ class CodexMcpAgentSession implements AgentSession {
if (timeline.length > 0) {
this.persistedHistory = timeline;
this.historyPending = true;
// Also populate SESSION_HISTORY so future in-process resumes work
SESSION_HISTORY.set(this.sessionId, [...timeline]);
}
}
@@ -3154,9 +3146,7 @@ class CodexMcpAgentSession implements AgentSession {
private recordHistory(item: AgentTimelineItem): void {
if (this.sessionId) {
const history = SESSION_HISTORY.get(this.sessionId) || [];
history.push(item);
SESSION_HISTORY.set(this.sessionId, history);
this.persistedHistory.push(item);
return;
}
this.pendingHistory.push(item);
@@ -3166,9 +3156,7 @@ class CodexMcpAgentSession implements AgentSession {
if (!this.sessionId || this.pendingHistory.length === 0) {
return;
}
const history = SESSION_HISTORY.get(this.sessionId) || [];
history.push(...this.pendingHistory);
SESSION_HISTORY.set(this.sessionId, history);
this.persistedHistory.push(...this.pendingHistory);
this.pendingHistory = [];
}