import type { SessionStatus, Message, Part } from "@opencode-ai/sdk/v2/client" import type { Session } from "@opencode-ai/sdk/v2" import { getSessionMaterializationStatus } from "./materialization" type ReconnectMaterializationState = { session: Session[] session_status?: Record message?: Record part?: Record } export type ViewedSessionMaterializationTarget = { directory: string sessionId: string } type ReconnectCandidateOptions = { directory?: string viewedSession?: ViewedSessionMaterializationTarget | null } export function getReconnectCandidateSessionIds(state: ReconnectMaterializationState, options?: ReconnectCandidateOptions) { const ids = new Set() for (const [sessionId, status] of Object.entries(state.session_status ?? {})) { if (status && status.type !== "idle") ids.add(sessionId) } for (const [sessionId, messages] of Object.entries(state.message ?? {})) { const lastMessage = messages[messages.length - 1] if ( lastMessage && lastMessage.role === "assistant" && typeof (lastMessage as { time?: { completed?: number } }).time?.completed !== "number" ) { ids.add(sessionId) } else if (!getSessionMaterializationStatus({ message: state.message ?? {}, part: state.part ?? {} }, sessionId).renderable) { ids.add(sessionId) } } const parentIds = new Set() for (const session of state.session) { const parentId = (session as Session & { parentID?: string | null }).parentID if (parentId) { parentIds.add(parentId) } } for (const pid of parentIds) { ids.add(pid) } const viewedSession = options?.viewedSession if (viewedSession?.sessionId && viewedSession.directory === options?.directory) { const sessionId = viewedSession.sessionId const sessionExists = state.session.some((session) => session.id === sessionId) || Object.hasOwn(state.session_status ?? {}, sessionId) || Object.hasOwn(state.message ?? {}, sessionId) if (sessionExists) { ids.add(sessionId) } } return Array.from(ids) }