export interface GroupMatrixChat { chatId: string; name?: string; avatar?: string; [key: string]: unknown; } export interface GroupsMatrix { chats: GroupMatrixChat[]; bots: unknown[]; } export interface GroupPresentation { chatId: string; name?: string; avatar?: string; } export interface CompactGroupsSnapshot { chats: GroupPresentation[]; } export interface GroupsMatrixSnapshotOptions { ttlMs?: number; retryMs?: number; now?: () => number; onRefreshError?: (error: unknown) => void; } export interface GroupsMatrixSnapshot { get: (options?: { force?: boolean; }) => Promise; warm: () => void; invalidate: () => void; peekPresentation: () => ReadonlyMap; } /** * Decide whether a role write (PUT/DELETE `/api/roles/:chatId`, or * `POST /api/role-profiles/:id/apply`) actually mutated the `hasRole` matrix * and should therefore invalidate the groups snapshot. * * `hasRole` (per bot × chat) feeds the roles-page「已配置/未配置」badge and the * groups card, so a stale snapshot leaves the badge wrong for up to the 30s TTL * — and the refresh button can't fix it (it hits `/api/groups` without * `refresh=1`). We invalidate on every successful write EXCEPT when the daemon * reports `changed: false`, which means the role FILE was not touched: * - `apply` preview mode, and no-op / refused applies; * - an injectMode-only PUT (writes just the `.meta.json` sidecar — `hasRole` * is unchanged, so the common inject-mode toggle must not bust the cache); * - a DELETE that removed nothing (`existed:false`). * Invalidating in those cases would punch through the 30s snapshot and undo the * fan-out savings this cache exists to provide. Responses that omit `changed` * entirely (e.g. a proxied text body we can't parse) still invalidate — a * successful write we can't introspect should refresh rather than stay stale. */ export declare function roleWriteShouldInvalidate(upstreamOk: boolean, body: unknown): boolean; export declare function compactGroupsMatrix(matrix: GroupsMatrix): CompactGroupsSnapshot; export declare function enrichSessionsWithGroupNames>(sessions: readonly T[], presentationByChatId: ReadonlyMap): T[]; export declare function createGroupsMatrixSnapshot(build: () => Promise, options?: GroupsMatrixSnapshotOptions): GroupsMatrixSnapshot; //# sourceMappingURL=groups-matrix-snapshot.d.ts.map