import type { Message, Part, PermissionRequest, QuestionRequest, SessionStatus, Todo, } from "@opencode-ai/sdk/v2/client" import type { FileDiff } from "./types" type SessionCache = { session_status: Record session_diff: Record todo: Record message: Record part: Record permission: Record question: Record } export function getProtectedSessionCacheIds(store: SessionCache): Set { const protectedIds = new Set() for (const [sessionID, status] of Object.entries(store.session_status ?? {})) { if (status && status.type !== "idle") { protectedIds.add(sessionID) } } for (const [sessionID, permissions] of Object.entries(store.permission ?? {})) { if ((permissions?.length ?? 0) > 0) { protectedIds.add(sessionID) } } for (const [sessionID, questions] of Object.entries(store.question ?? {})) { if ((questions?.length ?? 0) > 0) { protectedIds.add(sessionID) } } for (const [sessionID, messages] of Object.entries(store.message ?? {})) { const lastMessage = messages?.[messages.length - 1] if ( lastMessage?.role === "assistant" && typeof (lastMessage as { time?: { completed?: number } }).time?.completed !== "number" ) { protectedIds.add(sessionID) } } return protectedIds } export function dropSessionCaches(store: SessionCache, sessionIDs: Iterable) { const stale = new Set(Array.from(sessionIDs).filter(Boolean)) if (stale.size === 0) return const staleMessageIDs = new Set() for (const sessionID of stale) { for (const message of store.message?.[sessionID] ?? []) { if (message?.id) staleMessageIDs.add(message.id) } } for (const messageID of staleMessageIDs) { if (store.part) delete store.part[messageID] } for (const key of Object.keys(store.part ?? {})) { const parts = store.part[key] if (!parts?.some((part) => stale.has((part as { sessionID?: string })?.sessionID ?? ""))) continue delete store.part[key] } for (const sessionID of stale) { delete store.message[sessionID] delete store.todo[sessionID] delete store.session_diff[sessionID] delete store.session_status[sessionID] delete store.permission[sessionID] delete store.question[sessionID] } } export function pickSessionCacheEvictions(input: { seen: Set keep: string limit: number preserve?: Iterable }) { const stale: string[] = [] const keep = new Set([input.keep, ...Array.from(input.preserve ?? [])]) if (input.seen.has(input.keep)) input.seen.delete(input.keep) input.seen.add(input.keep) for (const id of input.seen) { if (input.seen.size - stale.length <= input.limit) break if (keep.has(id)) continue stale.push(id) } for (const id of stale) { input.seen.delete(id) } return stale }