import type { Logger } from "pino"; import type { AggregateDeviceSource } from "./device-sources/aggregate.js"; import type { DeviceDescriptor } from "./device-sources/device-source.js"; import { type StateManager } from "./state/state-manager.js"; /** * Reserved-namespace prefix under which each room definition is stored, * keyed by the room's stable identifier (design.md D14, D20). */ export declare const ROOM_PREFIX = "$internal:room:"; /** * Reserved-namespace prefix under which each device's room assignment is * stored, keyed by the device's qualified identifier. The value is the * assigned room's id (design.md D14, D29). */ export declare const ROOM_ASSIGNMENT_PREFIX = "$internal:room-assignment:"; /** Returns the reserved state key storing `id`'s room definition. */ export declare function roomKey(id: string): string; /** Returns the reserved state key storing `qualifiedId`'s room assignment. */ export declare function roomAssignmentKey(qualifiedId: string): string; /** A user-defined room: a stable identifier and a unique display name. */ export interface Room { readonly id: string; readonly name: string; } /** * One member of a room's membership listing. * * `available` is `false` when the device is no longer known to any device * source — unpaired, or its source disabled/unconfigured — in which case * `device` is `null` rather than stale data (design.md D14). */ export interface RoomMember { readonly qualifiedId: string; readonly available: boolean; readonly device: DeviceDescriptor | null; } /** A room together with its current membership. */ export interface RoomWithMembers extends Room { readonly members: RoomMember[]; } export type CreateRoomResult = { status: "ok"; room: Room; } | { status: "duplicate_name"; message: string; }; export type RenameRoomResult = { status: "ok"; room: Room; } | { status: "not_found"; } | { status: "duplicate_name"; message: string; }; export type DeleteRoomResult = "ok" | "not_found"; export type AssignDeviceResult = "ok" | "room_not_found"; /** * User-defined rooms that group devices across every device source * (design.md D14; specs/device-rooms/spec.md). * * Room definitions live under {@link ROOM_PREFIX} and device assignments * under {@link ROOM_ASSIGNMENT_PREFIX}, both inside the reserved internal * state namespace (design.md D20) — written through `setInternal()` / * `deleteInternal()` so neither is reachable through the public state API, * mirroring the automation-enabled-flag pattern in `automation-manager.ts`. * * A single assignment key per device (rather than a per-room member list) * makes reassignment a single write with no intermediate state in which a * device belongs to both or neither room, and lets the engine derive a * membership-change SSE delta straight from that one key's change event * without resending every room's full membership. */ export declare class RoomManager { private readonly stateManager; private readonly devices; private readonly logger; constructor(stateManager: StateManager, devices: AggregateDeviceSource, logger: Logger); /** * Create a room with the given display name. * * @returns `{ status: "duplicate_name" }` if a room with that name already * exists — no room is created. */ createRoom(name: string): CreateRoomResult; /** * Rename a room, preserving its membership (task 9.1). * * @returns `{ status: "not_found" }` for an unknown room id, or * `{ status: "duplicate_name" }` if another room already has that name. */ renameRoom(id: string, name: string): RenameRoomResult; /** * Delete a room. Its members are not deleted — they become unassigned * (task 9.1). */ deleteRoom(id: string): DeleteRoomResult; /** * Assign a device (by qualified identifier) to a room, as a single * atomic write — reassigning a device already in another room moves it, * with no intermediate state (task 9.2). Assigning to the room a device * is already in is idempotent and does not fire a change event, since the * underlying value does not change. * * @returns `{ status: "room_not_found" }` for an unknown room id. */ assignDevice(qualifiedId: string, roomId: string): AssignDeviceResult; /** Clear a device's room assignment, if any. Idempotent. */ unassignDevice(qualifiedId: string): void; /** The room a device belongs to, or `null` if it is unassigned or its room no longer exists. */ getRoomForDevice(qualifiedId: string): Room | null; /** Every room, with its current membership including unavailable members (task 9.4). */ listRooms(): RoomWithMembers[]; /** A single room by id, or `null` if unknown. */ getRoom(id: string): Room | null; /** * Every present device that belongs to no room (task 9.4). Absent devices * with no assignment are not meaningful here — they cannot be enumerated * at all outside of a room. */ getUnassignedDevices(): DeviceDescriptor[]; private toMember; private allRooms; private allAssignments; private findByName; } //# sourceMappingURL=room-manager.d.ts.map