import { BufferOutput, TowerState, ConnectionStatus, DeviceInformation, Lights, TowerSide, SealIdentifier, LogOutput, type UltimateDarkTowerConfig } from 'ultimatedarktower'; import { Glyphs } from 'ultimatedarktowerdata'; type BufferOutputType = InstanceType; export interface TowerSnapshot { connected: boolean; calibrated: boolean; performingLongCommand: boolean; performingCalibration: boolean; battery: { currentMillivolts: number; previousMillivolts: number; currentPercentage: number; previousPercentage: number; }; skullDropCount: number; connectionStatus: ConnectionStatus | null; deviceInfo: DeviceInformation | null; towerState: TowerState | null; brokenSeals: SealIdentifier[]; glyphs: Record; drumPositions: Record; } export interface TowerControllerConfig { /** * Config forwarded verbatim to the `UltimateDarkTower` constructor. Supply `{ adapter }` here to * inject a test/emulator BLE adapter (e.g. `MockBluetoothAdapter`) instead of letting the * controller pick a platform from `TOWER_PLATFORM`. When omitted, the env-based default is used — * so the published server behaves exactly as before, but is now embeddable/testable without * mocking the whole `ultimatedarktower` module. */ towerConfig?: UltimateDarkTowerConfig; } export declare class TowerController { private readonly config; private static instance; private tower; private lastTowerState; private lastDeviceInfo; private lastConnectionStatus; private skullCount; private pendingCalibration; private bufferOutput; private constructor(); /** * Returns the process-wide singleton, creating it on first call. `config` is honored only on that * first call (the singleton is created once); later calls return the existing instance. */ static getInstance(config?: TowerControllerConfig): TowerController; private ensureTower; setLoggerOutputs(outputs: LogOutput[]): void; /** * The rolling in-memory log buffer (last ~500 entries) that `setLoggerOutputs` always keeps * attached. Exposed so a diagnostics readout can surface recent driver activity — previously the * buffer was filled on every log line but never readable. */ getBuffer(): ReturnType; getBufferSize(): number; get isConnected(): boolean; get isCalibrated(): boolean; get performingLongCommand(): boolean; get performingCalibration(): boolean; connect(): Promise; disconnect(): Promise; cleanup(): Promise; isConnectedAndResponsive(): Promise; getConnectionStatus(): ConnectionStatus | null; getDeviceInformation(): DeviceInformation | null; setConnectionMonitoring(enabled: boolean): void; configureConnectionMonitoring(frequency?: number, timeout?: number): void; configureBatteryHeartbeatMonitoring(enabled?: boolean, timeout?: number, verifyConnection?: boolean): void; /** * Calibrates the tower and waits for the tower to report completion. * * The wait is bounded: completion arrives via a callback, and a jammed drum or a * BLE drop mid-calibration means it may never arrive at all. Without a timeout the * returned promise never settles and the MCP client hangs with no error to report. * * @throws {Error} If calibration does not complete within CALIBRATION_TIMEOUT_MS, * or if a later calibrate() call supersedes this one. */ calibrate(): Promise; /** * Settles the in-flight calibration, if any. Rejects it when given an error, * resolves it otherwise. Safe to call when nothing is pending. */ private settlePendingCalibration; playSoundStateful(soundIndex: number, loop?: boolean, volume?: number): Promise; lights(lights: Lights): Promise; setLED(layerIndex: number, lightIndex: number, effect: number, loop?: boolean): Promise; allLightsOn(effect?: number): Promise; allLightsOff(): Promise; lightOverrides(sequence: number, soundIndex?: number): Promise; rotateWithState(top: TowerSide, middle: TowerSide, bottom: TowerSide, soundIndex?: number): Promise; rotateDrumStateful(drumIndex: number, position: number, playSound?: boolean): Promise; randomRotateLevels(level?: number): Promise; getCurrentDrumPosition(level: 'top' | 'middle' | 'bottom'): TowerSide; breakSeal(seal: SealIdentifier, volume?: number): Promise; isSealBroken(seal: SealIdentifier): boolean; getBrokenSeals(): SealIdentifier[]; resetBrokenSeals(): void; getRandomUnbrokenSeal(): SealIdentifier | null; getCurrentTowerState(): TowerState | null; sendTowerState(state: TowerState): Promise; getGlyphPosition(glyph: Glyphs): TowerSide | null; getAllGlyphPositions(): Record; getGlyphsFacingDirection(direction: TowerSide): Glyphs[]; get towerSkullDropCount(): number; resetTowerSkullCount(): Promise; getSnapshot(): TowerSnapshot; private getDrumPositionsMap; private requireConnected; private requireCalibrated; } /** * Wraps a tool handler to catch UDT errors and return MCP-friendly error responses. */ export declare function wrapToolHandler(fn: () => Promise): Promise<{ content: Array<{ type: 'text'; text: string; }>; isError?: boolean; }>; export {}; //# sourceMappingURL=tower-controller.d.ts.map