import type { Session as SessionDetails } from "../types.js"; import type { RailSession as Session } from "./session-list-entry.js"; export type SessionBranchPage = { sessions: T[]; /** Per-row causal generations for rows returned by accepted branch reads. */ channelGenerations: ReadonlyMap; nextCursor: string | null; loading: boolean; /** Whether this load cycle may paint loading or retry feedback in the tree. */ feedbackVisible: boolean; failed: boolean; stale: boolean; requestId: number | null; retryCursor: string | null; }; export type SessionBranchSummaryDecision = { acknowledge: boolean; refresh: boolean; markStale: boolean; }; /** * Stable summary of the server-owned descendant facts that make an already * loaded branch stale. Child creation changes direct/total counts; lifecycle * changes advance the status aggregates. Title/content stays owned by the * child page or active route projection. */ export declare function sessionBranchSummaryKey(session: Session, readRevision?: number): string; /** * Persist a route/lineage child in its already-loaded parent branch. The route * owns current lifecycle/content while the cached row retains rail ordering * timestamps and may own treeStats. */ export declare function upsertSessionBranchChild(pages: ReadonlyMap>, child: SessionDetails): ReadonlyMap>; export declare function upsertSessionBranchChild(pages: ReadonlyMap>, child: T): ReadonlyMap>; /** Mark one exact branch request active without discarding loaded children. */ export declare function beginSessionBranchRequest(pages: ReadonlyMap>, parentSessionId: string, requestId: number, cursor?: string, options?: { feedbackVisible?: boolean | undefined; }): ReadonlyMap>; /** Refresh the already-loaded window with bounded, opaque-cursor reads. */ export declare function readLoadedSessionBranchWindow(readPage: (cursor?: string) => Promise<{ sessions: T[]; pinned: T[]; nextCursor: string | null; }>, minimumCount: number, initialCursor?: string): Promise<{ sessions: T[]; nextCursor: string | null; }>; /** Commit one server child page or a fully refreshed loaded window. */ export declare function commitSessionBranchPage(pages: ReadonlyMap>, parentSessionId: string, input: { sessions: readonly SessionDetails[]; nextCursor: string | null; }, options?: { append?: boolean | undefined; replaceWindow?: boolean | undefined; preserve?: readonly SessionDetails[] | undefined; requestId?: number | undefined; readGeneration?: number | undefined; }): ReadonlyMap>; export declare function commitSessionBranchPage(pages: ReadonlyMap>, parentSessionId: string, input: { sessions: readonly T[]; nextCursor: string | null; }, options?: { append?: boolean | undefined; replaceWindow?: boolean | undefined; preserve?: readonly T[] | undefined; requestId?: number | undefined; readGeneration?: number | undefined; }): ReadonlyMap>; /** Current branch rows that may own channel filing, with their actual read starts. */ export declare function authoritativeSessionBranchChannels(page: SessionBranchPage): Array; /** Fail only the still-current request and expose its exact retry cursor. */ export declare function failSessionBranchRequest(pages: ReadonlyMap>, parentSessionId: string, requestId: number): ReadonlyMap>; /** A fresh cached page already owns the active child's parent branch. */ export declare function sessionBranchNeedsHydration(page: SessionBranchPage | undefined): boolean; /** Decide whether a changed parent summary can be acknowledged right now. */ export declare function sessionBranchSummaryDecision(input: { previousKey: string | undefined; nextKey: string; loading: boolean; expanded: boolean; stale: boolean; }): SessionBranchSummaryDecision;