(
sessionId: string,
logger: Logger,
)
| 113 | } |
| 114 | |
| 115 | export async function loadSessionState( |
| 116 | sessionId: string, |
| 117 | logger: Logger, |
| 118 | ): Promise<PersistedSessionState | null> { |
| 119 | try { |
| 120 | const filePath = getSessionFilePath(sessionId) |
| 121 | |
| 122 | if (!existsSync(filePath)) { |
| 123 | return null |
| 124 | } |
| 125 | |
| 126 | const content = await fs.readFile(filePath, "utf-8") |
| 127 | const state = JSON.parse(content) as PersistedSessionState |
| 128 | |
| 129 | const hasPruneTools = state?.prune?.tools && typeof state.prune.tools === "object" |
| 130 | const hasPruneMessages = state?.prune?.messages && typeof state.prune.messages === "object" |
| 131 | const hasNudgeFormat = state?.nudges && typeof state.nudges === "object" |
| 132 | if ( |
| 133 | !state || |
| 134 | !state.prune || |
| 135 | !hasPruneTools || |
| 136 | !hasPruneMessages || |
| 137 | !state.stats || |
| 138 | !hasNudgeFormat |
| 139 | ) { |
| 140 | logger.warn("Invalid session state file, ignoring", { |
| 141 | sessionId: sessionId, |
| 142 | }) |
| 143 | return null |
| 144 | } |
| 145 | |
| 146 | const rawContextLimitAnchors = Array.isArray(state.nudges.contextLimitAnchors) |
| 147 | ? state.nudges.contextLimitAnchors |
| 148 | : [] |
| 149 | const validAnchors = rawContextLimitAnchors.filter( |
| 150 | (entry): entry is string => typeof entry === "string", |
| 151 | ) |
| 152 | const dedupedAnchors = [...new Set(validAnchors)] |
| 153 | if (validAnchors.length !== rawContextLimitAnchors.length) { |
| 154 | logger.warn("Filtered out malformed contextLimitAnchors entries", { |
| 155 | sessionId: sessionId, |
| 156 | original: rawContextLimitAnchors.length, |
| 157 | valid: validAnchors.length, |
| 158 | }) |
| 159 | } |
| 160 | state.nudges.contextLimitAnchors = dedupedAnchors |
| 161 | |
| 162 | const rawTurnNudgeAnchors = Array.isArray(state.nudges.turnNudgeAnchors) |
| 163 | ? state.nudges.turnNudgeAnchors |
| 164 | : [] |
| 165 | const validSoftAnchors = rawTurnNudgeAnchors.filter( |
| 166 | (entry): entry is string => typeof entry === "string", |
| 167 | ) |
| 168 | const dedupedSoftAnchors = [...new Set(validSoftAnchors)] |
| 169 | if (validSoftAnchors.length !== rawTurnNudgeAnchors.length) { |
| 170 | logger.warn("Filtered out malformed turnNudgeAnchors entries", { |
| 171 | sessionId: sessionId, |
| 172 | original: rawTurnNudgeAnchors.length, |
no test coverage detected